/** * @param int|string $m * @param string $path * @param array $keys * @param HierarchicalKeySequence $sequences * @param bool $sort */ public function __construct($m, $path, array $keys, HierarchicalKeySequence $sequences, $sort = false) { if (count($keys) < 1) { throw new \RuntimeException('Must have at least one HierarchicalKey for Multisig HD Script'); } // Sort here to guarantee calls to getKeys() returns keys in the same order as the redeemScript. if ($sort) { $keys = $this->sortHierarchicalKeys($keys); } foreach ($keys as $key) { $this->keys[] = $key; } $this->m = $m; $this->path = $path; $this->sort = $sort; $this->sequences = $sequences; $this->redeemScript = ScriptFactory::p2sh()->multisig($m, array_map(function (HierarchicalKey $key) { return $key->getPublicKey(); }, $this->keys)); }
public function testComposeP2SHSourceCounterpartyTransaction() { list($sender_address_1, $wif_key_1, $private_key_1) = $this->newAddressAndKey(); list($sender_address_2, $wif_key_2, $private_key_2) = $this->newAddressAndKey(); list($sender_address_3, $wif_key_3, $private_key_3) = $this->newAddressAndKey(); // build a multisig address (2 of 3) $public_keys = [$private_key_1->getPublicKey(), $private_key_2->getPublicKey(), $private_key_3->getPublicKey()]; $p2sh_script = ScriptFactory::p2sh()->multisig(2, $public_keys); $sender_address = $p2sh_script->getAddress()->getAddress(); // variables $utxos = $this->fakeUTXOs($sender_address); $asset = 'SOUP'; $quantity = 45; $destination = '1AAAA1111xxxxxxxxxxxxxxxxxxy43CZ9j'; $fee = 0.0001; $btc_dust = 5.432E-5; // compose the send $composer = new Composer(); $composed_unsigned_send = $composer->composeSend($asset, CryptoQuantity::fromFloat($quantity), $destination, null, $utxos, $sender_address, $fee, $btc_dust); list($txid, $unsigned_hex, $new_utxos) = $this->decomposeComposedTransaction($composed_unsigned_send); // parse the signed hex $transaction = TransactionFactory::fromHex($unsigned_hex); // check output 1 $tx_output_0 = $transaction->getOutput(0); PHPUnit::assertEquals(intval(round($btc_dust * self::SATOSHI)), $tx_output_0->getValue()); PHPUnit::assertEquals($destination, AddressFactory::fromOutputScript($tx_output_0->getScript())->getAddress()); // check output 2 $tx_output_1 = $transaction->getOutput(1); $op_return = $tx_output_1->getScript()->getScriptParser()->decode()[1]->getData()->getHex(); $txid = $transaction->getInput(0)->getOutPoint()->getTxId()->getHex(); $hex = $this->arc4decrypt($txid, $op_return); $expected_hex = '434e54525052545900000000000000000004fadf000000010c388d00'; PHPUnit::assertEquals($expected_hex, $hex); // check output 3 $tx_output_2 = $transaction->getOutput(2); PHPUnit::assertEquals(intval(round((0.123 + 0.0005 - $fee - $btc_dust) * self::SATOSHI)), $tx_output_2->getValue()); PHPUnit::assertEquals($sender_address, AddressFactory::fromOutputScript($tx_output_2->getScript())->getAddress()); // check $new_utxos PHPUnit::assertNotEmpty($new_utxos); PHPUnit::assertEquals(5432, $new_utxos[0]['amount']); }