From f0c7eab26598d5e965409c50c57c9a0a490a4405 Mon Sep 17 00:00:00 2001 From: jrakibi Date: Mon, 17 Feb 2025 22:00:35 +0700 Subject: [PATCH] remove implement-OP_ADD-OP_HASH160.mdx --- decoding/implement-OP_ADD-OP_HASH160.mdx | 394 ----------------------- 1 file changed, 394 deletions(-) delete mode 100644 decoding/implement-OP_ADD-OP_HASH160.mdx diff --git a/decoding/implement-OP_ADD-OP_HASH160.mdx b/decoding/implement-OP_ADD-OP_HASH160.mdx deleted file mode 100644 index 58e8801..0000000 --- a/decoding/implement-OP_ADD-OP_HASH160.mdx +++ /dev/null @@ -1,394 +0,0 @@ ---- -title: "Implement OP_ADD, OP_HASH160" -date: 2024-01-05T15:32:14Z -lastmod: "2024-10-06" -draft: false -category: Scripts -layout: TopicBanner -order: 4 -project: true -images: - [ - "/decoding-bitcoin/static/images/topics/thumbnails/project-stack-thumbnail.webp" - ] -parent: project ---- - -In Bitcoin script, OP_ADD adds the top two items on the stack, while OP_HASH160 computes the RIPEMD160(SHA256(x)) hash of the top stack item. - -## Task - -Complete the `OP_ADD` and `OP_HASH160` functions in `challenges/OpcodeFunctions.js`: - -1. Implement `OP_ADD` to add the top two stack items, handling Bitcoin's number encoding. -2. Implement `OP_HASH160` to compute the RIPEMD160(SHA256(x)) hash of the top stack item. - -## Implementation - ->>= 8; - } - - if (result[result.length - 1] & 0x80) { - if (negative) { - result.push(0x80); - } else { - result.push(0); - } - } else if (negative) { - result[result.length - 1] |= 0x80; - } - - return Buffer.from(result); - -} - -export function decodeNum(buffer) { - if (buffer.length === 0) return 0; - - const bigEndian = Buffer.from(buffer).reverse(); - let result = 0; - const negative = bigEndian[0] & 0x80; - - if (negative) { - result = bigEndian[0] & 0x7f; - } else { - result = bigEndian[0]; - } - - for (let i = 1; i < bigEndian.length; i++) { - result <<= 8; - result += bigEndian[i]; - } - - if (negative) { - return -result; - } else { - return result; - } - -} - -export const OP_ADD = (stack) => { - // TODO: Implement OP_ADD -} - -export const OP_HASH160 = (stack) => { - // TODO: Implement OP_HASH160 -} - -export const OP_CODE_FUNCTIONS = { - OP_ADD, - OP_HASH160 - // Add more opcodes here -}`, - active: true - }, - "/OpcodeSimulator.js": { - code: ` -import React, { useState } from "react" -import { motion, AnimatePresence } from "framer-motion" -import { ArrowDownCircle, ArrowUpCircle, Info } from "lucide-react" -import { OP_CODE_FUNCTIONS, decodeNum } from "./challenges/OpcodeFunctions" - -const OpcodeSimulator = () => { -const [stack, setStack] = useState([]); -const [input, setInput] = useState('0x'); -const [lastOperation, setLastOperation] = useState(null); -const [showHexInfo, setShowHexInfo] = useState(false); -const [scriptAsm, setScriptAsm] = useState(''); - - const handleInputChange = (e) => { - const value = e.target.value; - if (value.length < 2) { - setInput('0x'); - } else if (value.startsWith('0x')) { - const hexPart = value.slice(2); - if (/^[0-9A-Fa-f]*$/.test(hexPart)) { - setInput(value); - } - } - }; - - const push = () => { - if (input.length > 2) { - const hexValue = input.slice(2); - setStack([...stack, Buffer.from(hexValue, 'hex')]); - setInput('0x'); - setLastOperation("push"); - } - }; - - const pop = () => { - if (stack.length > 0) { - setStack(stack.slice(0, -1)); - setLastOperation("pop"); - } - }; - - const executeOpcode = (opcodeName) => { - try { - const newStack = [...stack]; - OP_CODE_FUNCTIONS[opcodeName](newStack); - setStack(newStack); - setLastOperation(opcodeName); - } catch (error) { - console.error("Error executing " + opcodeName + ":", error); - setLastOperation(opcodeName + " (failed)"); - } - }; - - const getItemColor = (item) => { - if (item.toString().startsWith("Error:")) { - return "bg-red-500 text-white"; - } - if (item.length === 1) { - const value = item[0]; - if (value === 0x01) { - return "bg-green-500 text-white"; // Success (true) - } else if (value === 0x00) { - return "bg-red-500 text-white"; // Failure (false) - } - } - return "bg-purple-500 text-white"; // Default color - }; - - const formatStackItem = (item) => { - if (item.toString().startsWith("Error:")) { - return {item.toString()}; - } - if (item.length === 1) { - const value = item[0]; - if (value === 0x01) { - return true (0x01); - } else if (value === 0x00) { - return false (0x00); - } - } - const hex = "0x" + item.toString('hex'); - try { - const num = decodeNum(item); - return {hex} ({num}); - } catch { - return {hex}; - } - }; - - return ( -
- -
- Bitcoin Stack Evaluator -
- -
-
- e.target.setSelectionRange(2, 2)} - /> - -
-
- - - Push - - - - Pop - -
-
- - {showHexInfo && ( -
-

- Enter values in hexadecimal format only (e.g., 0x01, 0xff). - The '0x' prefix is fixed to indicate hex input. - For arithmetic operations, the hex values will be interpreted as numbers. -

-
- )} - -
- {Object.keys(OP_CODE_FUNCTIONS).map((opcodeName) => ( - executeOpcode(opcodeName)} - className="px-2 py-1 bg-gray-100 text-gray-800 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-opacity-50 text-sm w-full" - > - {opcodeName} - - ))} -
- -
-
- Stack (Last-In-First-Out): -
- - {stack.length === 0 ? ( - - Stack is empty - - ) : ( -
- {stack.slice().reverse().map((item, index) => ( - -
- {formatStackItem(item)} -
-
- ))} -
- )} -
-
- - {lastOperation && ( -
- Last operation: {lastOperation} -
- )} -
-
- ); - -}; - -export default OpcodeSimulator`, - hidden: false - }, - "/App.js": { - code: ` -import React from "react" -import OpcodeSimulator from "./OpcodeSimulator" - -const App = () => { -return ( - -
-

Bitcoin Opcode Challenge

- -
-); }; - -export default App; -`, - hidden: false - } - }, - options: { - externalResources: ['https://cdn.tailwindcss.com'], - showLineNumbers: true, - showInlineErrors: true, - editorHeight: 500 - }, - customSetup: { - dependencies: { - "react": "^18.0.0", - "react-dom": "^18.0.0", - "lucide-react": "^0.390.0", - "framer-motion": "^11.3.21", - "crypto-js": "^4.1.1" - }, - } - }} - trinketUrl="https://trinket.io/embed/python3/12cf9af5968a" -/> - -## Hints - - - -## Solution - - -```javascript -export function OP_ADD(stack) { - if (stack.length < 2) throw new Error("Insufficient items for OP_ADD"); - const b = decodeNum(stack.pop()); - const a = decodeNum(stack.pop()); - stack.push(encodeNum(a + b)); -} - -export function OP_HASH160(stack) { - if (stack.length < 1) throw new Error("Insufficient items for OP_HASH160"); - const item = stack.pop(); - const sha256 = CryptoJS.SHA256(CryptoJS.lib.WordArray.create(item)); - const ripemd160 = CryptoJS.RIPEMD160(sha256); - stack.push(Buffer.from(ripemd160.toString(), 'hex')); -} -``` - - - -Test your implementation using the Bitcoin Opcode Simulator above. Try various inputs to ensure your opcodes handle different scenarios correctly.