/**
  * @param $opCode
  * @param ScriptStack $mainStack
  * @param ScriptStack $vfStack
  * @param $fExec
  * @throws \BitWasp\Bitcoin\Exceptions\ScriptStackException
  * @throws \Exception
  */
 public function op($opCode, ScriptStack $mainStack, ScriptStack $vfStack, $fExec)
 {
     $opCodes = $this->opCodes;
     $castToBool = $this->castToBool;
     $opName = $opCodes->getOp($opCode);
     if ($opName == 'OP_NOP') {
         return;
     } elseif (in_array($opName, ['OP_IF', 'OP_NOTIF'])) {
         // cscriptnum
         // <expression> if [statements] [else [statements]] endif
         $value = false;
         if ($fExec) {
             if ($mainStack->size() < 1) {
                 throw new \Exception('Unbalanced conditional');
             }
             // todo
             $buffer = $mainStack->pop();
             $value = $castToBool($buffer);
             if ($opCodes->isOp($opCode, 'OP_NOTIF')) {
                 $value = !$value;
             }
         }
         $vfStack->push($value);
         return;
     } else {
         if ($opName == 'OP_ELSE') {
             if ($vfStack->size() == 0) {
                 throw new \Exception('Unbalanced conditional');
             }
             $vfStack->set($vfStack->end() - 1, !$vfStack->end());
             return;
         } else {
             if ($opName == 'OP_ENDIF') {
                 if ($vfStack->size() == 0) {
                     throw new \Exception('Unbalanced conditional');
                 }
                 // todo
                 return;
             } else {
                 if ($opName == 'OP_VERIFY') {
                     if ($mainStack->size() < 1) {
                         throw new \Exception('Invalid stack operation');
                     }
                     $value = $castToBool($mainStack->top(-1));
                     if (!$value) {
                         throw new \Exception('Error: verify');
                     }
                     $mainStack->pop();
                     return;
                 } else {
                     if ($opName == 'OP_RETURN') {
                         throw new \Exception('Error: OP_RETURN');
                     }
                 }
             }
         }
     }
     throw new \Exception('Opcode not found');
 }
Ejemplo n.º 2
0
 /**
  * @param $opCode
  * @param ScriptStack $mainStack
  * @throws \BitWasp\Bitcoin\Exceptions\ScriptStackException
  * @throws \Exception
  */
 public function op($opCode, ScriptStack $mainStack)
 {
     if ($mainStack->size() < 1) {
         throw new \Exception('Invalid stack operation');
     }
     $opCodes = $this->opCodes;
     $opName = $opCodes->getOp($opCode);
     $buffer = $mainStack->top(-1);
     if ($opCodes->cmp($opCode, 'OP_RIPEMD160') >= 0 && $opCodes->cmp($opCode, 'OP_HASH256') <= 0) {
         if ($opName == 'OP_RIPEMD160') {
             $hash = Hash::ripemd160($buffer);
         } elseif ($opName == 'OP_SHA1') {
             $hash = Hash::sha1($buffer);
         } elseif ($opName == 'OP_SHA256') {
             $hash = Hash::sha256($buffer);
         } elseif ($opName == 'OP_HASH160') {
             $hash = Hash::sha256ripe160($buffer);
         } else {
             // is hash256
             $hash = Hash::sha256d($buffer);
         }
         $mainStack->pop();
         $mainStack->push($hash);
     } else {
         throw new \Exception('Opcode not found');
     }
 }
Ejemplo n.º 3
0
 /**
  * @param $opCode
  * @param ScriptStack $mainStack
  * @param ScriptStack $altStack
  * @throws \BitWasp\Bitcoin\Exceptions\ScriptStackException
  * @throws \Exception
  */
 public function op($opCode, ScriptStack $mainStack, ScriptStack $altStack)
 {
     $opCodes = $this->opCodes;
     $opName = $this->opCodes->getOp($opCode);
     $castToBool = $this->castToBool;
     if ($opName == 'OP_TOALTSTACK') {
         if ($mainStack->size() < 1) {
             throw new \Exception('Invalid stack operation OP_TOALTSTACK');
         }
         $altStack->push($mainStack->pop());
         return;
     } else {
         if ($opName == 'OP_FROMALTSTACK') {
             if ($altStack->size() < 1) {
                 throw new \Exception('Invalid alt-stack operation OP_FROMALTSTACK');
             }
             $mainStack->push($altStack->pop());
             return;
         } else {
             if ($opName == 'OP_IFDUP') {
                 // If top value not zero, duplicate it.
                 if ($mainStack->size() < 1) {
                     throw new \Exception('Invalid stack operation OP_IFDUP');
                 }
                 $vch = $mainStack->top(-1);
                 if ($castToBool($vch)) {
                     $mainStack->push($vch);
                 }
                 return;
             } else {
                 if ($opName == 'OP_DEPTH') {
                     $num = $mainStack->size();
                     $bin = Buffer::hex($this->math->decHex($num));
                     $mainStack->push($bin);
                     return;
                 } else {
                     if ($opName == 'OP_DROP') {
                         if ($mainStack->size() < 1) {
                             throw new \Exception('Invalid stack operation OP_DROP');
                         }
                         $mainStack->pop();
                         return;
                     } else {
                         if ($opName == 'OP_DUP') {
                             if ($mainStack->size() < 1) {
                                 throw new \Exception('Invalid stack operation OP_DUP');
                             }
                             $vch = $mainStack->top(-1);
                             $mainStack->push($vch);
                             return;
                         } else {
                             if ($opName == 'OP_NIP') {
                                 if ($mainStack->size() < 2) {
                                     throw new \Exception('Invalid stack operation OP_NIP');
                                 }
                                 $mainStack->erase(-2);
                                 return;
                             } else {
                                 if ($opName == 'OP_OVER') {
                                     if ($mainStack->size() < 2) {
                                         throw new \Exception('Invalid stack operation OP_OVER');
                                     }
                                     $vch = $mainStack->top(-2);
                                     $mainStack->push($vch);
                                     return;
                                 } else {
                                     if (in_array($opName, ['OP_PICK', 'OP_ROLL'])) {
                                         // cscriptnum
                                         if ($mainStack->size() < 2) {
                                             throw new \Exception('Invalid stack operation OP_PICK');
                                         }
                                         $n = $mainStack->top(-1)->getInt();
                                         $mainStack->pop();
                                         if ($this->math->cmp($n, 0) < 0 || $this->math->cmp($n, $mainStack->size()) >= 0) {
                                             throw new \Exception('Invalid stack operation OP_PICK');
                                         }
                                         $pos = $this->math->sub($this->math->sub(0, $n), 1);
                                         $vch = $mainStack->top($pos);
                                         if ($opCodes->isOp($opCode, 'OP_ROLL')) {
                                             $mainStack->erase($pos);
                                         }
                                         $mainStack->push($vch);
                                         return;
                                     } else {
                                         if ($opName == 'OP_ROT') {
                                             if ($mainStack->size() < 3) {
                                                 throw new \Exception('Invalid stack operation OP_ROT');
                                             }
                                             $mainStack->swap(-3, -2);
                                             $mainStack->swap(-2, -1);
                                             return;
                                         } else {
                                             if ($opName == 'OP_SWAP') {
                                                 if ($mainStack->size() < 2) {
                                                     throw new \Exception('Invalid stack operation OP_SWAP');
                                                 }
                                                 $mainStack->swap(-2, -1);
                                                 return;
                                             } else {
                                                 if ($opName == 'OP_TUCK') {
                                                     if ($mainStack->size() < 2) {
                                                         throw new \Exception('Invalid stack operation OP_TUCK');
                                                     }
                                                     $vch = $mainStack->top(-1);
                                                     $mainStack->insert($mainStack->end() - 2, $vch);
                                                     return;
                                                 } else {
                                                     if ($opName == 'OP_2DROP') {
                                                         if ($mainStack->size() < 2) {
                                                             throw new \Exception('Invalid stack operation OP_2DROP');
                                                         }
                                                         $mainStack->pop();
                                                         $mainStack->pop();
                                                         return;
                                                     } else {
                                                         if ($opName == 'OP_2DUP') {
                                                             if ($mainStack->size() < 2) {
                                                                 throw new \Exception('Invalid stack operation OP_2DUP');
                                                             }
                                                             $string1 = $mainStack->top(-2);
                                                             $string2 = $mainStack->top(-1);
                                                             $mainStack->push($string1);
                                                             $mainStack->push($string2);
                                                             return;
                                                         } else {
                                                             if ($opName == 'OP_3DUP') {
                                                                 if ($mainStack->size() < 3) {
                                                                     throw new \Exception('Invalid stack operation OP_3DUP');
                                                                 }
                                                                 $string1 = $mainStack->top(-3);
                                                                 $string2 = $mainStack->top(-2);
                                                                 $string3 = $mainStack->top(-1);
                                                                 $mainStack->push($string1);
                                                                 $mainStack->push($string2);
                                                                 $mainStack->push($string3);
                                                                 return;
                                                             } else {
                                                                 if ($opName == 'OP_2OVER') {
                                                                     if ($mainStack->size() < 4) {
                                                                         throw new \Exception('Invalid stack operation OP_2OVER');
                                                                     }
                                                                     $string1 = $mainStack->top(-4);
                                                                     $string2 = $mainStack->top(-3);
                                                                     $mainStack->push($string1);
                                                                     $mainStack->push($string2);
                                                                     return;
                                                                 } else {
                                                                     if ($opName == 'OP_2ROT') {
                                                                         if ($mainStack->size() < 6) {
                                                                             throw new \Exception('Invalid stack operation OP_2ROT');
                                                                         }
                                                                         $string1 = $mainStack->top(-6);
                                                                         $string2 = $mainStack->top(-5);
                                                                         $mainStack->erase(-6);
                                                                         $mainStack->erase(-5);
                                                                         $mainStack->push($string1);
                                                                         $mainStack->push($string2);
                                                                         return;
                                                                     } else {
                                                                         if ($opName == 'OP_2SWAP') {
                                                                             if ($mainStack->size() < 4) {
                                                                                 throw new \Exception('Invalid stack operation OP_2SWAP');
                                                                             }
                                                                             $mainStack->swap(-3, -1);
                                                                             $mainStack->swap(-4, -2);
                                                                             return;
                                                                         }
                                                                     }
                                                                 }
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     throw new \Exception('Opcode not found');
 }
 /**
  * @param $opCode
  * @param ScriptStack $mainStack
  * @throws \BitWasp\Bitcoin\Exceptions\ScriptStackException
  * @throws \Exception
  */
 private function threeValueCases($opCode, ScriptStack $mainStack)
 {
     $opName = $this->opCodes->getOp($opCode);
     $math = $this->math;
     if ($opName == 'OP_WITHIN') {
         //cscriptnum
         if ($mainStack->size() < 3) {
             throw new \Exception('Invalid stack operation');
         }
         $num1 = $mainStack->top(-3)->getInt();
         $num2 = $mainStack->top(-2)->getInt();
         $num3 = $mainStack->top(-1)->getInt();
         $value = $math->cmp($num2, $num1) <= 0 && $math->cmp($num1, $num3) < 0;
         $mainStack->pop();
         $mainStack->pop();
         $mainStack->pop();
         $mainStack->push($value ? $this->_bn1 : $this->_bn0);
         return;
     }
     throw new \Exception('Opcode not found');
 }