All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.bitcoin.script.ScriptBuilder Maven / Gradle / Ivy

There is a newer version: 0.11.3
Show newest version
/*
 * Copyright 2013 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.bitcoin.script;

import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.crypto.TransactionSignature;
import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static com.google.bitcoin.script.ScriptOpCodes.*;
import static com.google.common.base.Preconditions.checkArgument;

/**
 * 

Tools for the construction of commonly used script types. You don't normally need this as it's hidden behind * convenience methods on {@link com.google.bitcoin.core.Transaction}, but they are useful when working with the * protocol at a lower level.

*/ public class ScriptBuilder { private List chunks; public ScriptBuilder() { chunks = Lists.newLinkedList(); } public ScriptBuilder op(int opcode) { chunks.add(new ScriptChunk(true, new byte[]{(byte)opcode})); return this; } public ScriptBuilder data(byte[] data) { byte[] copy = Arrays.copyOf(data, data.length); chunks.add(new ScriptChunk(false, copy)); return this; } public ScriptBuilder smallNum(int num) { checkArgument(num >= 0, "Cannot encode negative numbers with smallNum"); checkArgument(num <= 16, "Cannot encode numbers larger than 16 with smallNum"); chunks.add(new ScriptChunk(true, new byte[]{(byte)Script.encodeToOpN(num)})); return this; } public Script build() { return new Script(chunks); } /** Creates a scriptPubKey that encodes payment to the given address. */ public static Script createOutputScript(Address to) { if (to.isP2SHAddress()) { // OP_HASH160 OP_EQUAL return new ScriptBuilder() .op(OP_HASH160) .data(to.getHash160()) .op(OP_EQUAL) .build(); } else { // OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG return new ScriptBuilder() .op(OP_DUP) .op(OP_HASH160) .data(to.getHash160()) .op(OP_EQUALVERIFY) .op(OP_CHECKSIG) .build(); } } /** Creates a scriptPubKey that encodes payment to the given raw public key. */ public static Script createOutputScript(ECKey key) { return new ScriptBuilder().data(key.getPubKey()).op(OP_CHECKSIG).build(); } /** Creates a scriptSig that can redeem a pay-to-address output. */ public static Script createInputScript(TransactionSignature signature, ECKey pubKey) { byte[] pubkeyBytes = pubKey.getPubKey(); return new ScriptBuilder().data(signature.encodeToBitcoin()).data(pubkeyBytes).build(); } /** Creates a scriptSig that can redeem a pay-to-pubkey output. */ public static Script createInputScript(TransactionSignature signature) { return new ScriptBuilder().data(signature.encodeToBitcoin()).build(); } /** Creates a program that requires at least N of the given keys to sign, using OP_CHECKMULTISIG. */ public static Script createMultiSigOutputScript(int threshold, List pubkeys) { checkArgument(threshold > 0); checkArgument(threshold <= pubkeys.size()); checkArgument(pubkeys.size() <= 16); // That's the max we can represent with a single opcode. ScriptBuilder builder = new ScriptBuilder(); builder.smallNum(threshold); for (ECKey key : pubkeys) { builder.data(key.getPubKey()); } builder.smallNum(pubkeys.size()); builder.op(OP_CHECKMULTISIG); return builder.build(); } /** Create a program that satisfies an OP_CHECKMULTISIG program. */ public static Script createMultiSigInputScript(List signatures) { List sigs = new ArrayList(signatures.size()); for (TransactionSignature signature : signatures) sigs.add(signature.encodeToBitcoin()); return createMultiSigInputScriptBytes(sigs); } /** Create a program that satisfies an OP_CHECKMULTISIG program. */ public static Script createMultiSigInputScript(TransactionSignature... signatures) { return createMultiSigInputScript(Arrays.asList(signatures)); } /** Create a program that satisfies an OP_CHECKMULTISIG program, using pre-encoded signatures. */ public static Script createMultiSigInputScriptBytes(List signatures) { checkArgument(signatures.size() <= 16); ScriptBuilder builder = new ScriptBuilder(); builder.smallNum(0); // Work around a bug in CHECKMULTISIG that is now a required part of the protocol. for (byte[] signature : signatures) builder.data(signature); return builder.build(); } /** * Creates a scriptPubKey that sends to the given script hash. Read * BIP 16 to learn more about this * kind of script. */ public static Script createP2SHOutputScript(byte[] hash) { checkArgument(hash.length == 20); return new ScriptBuilder().op(OP_HASH160).data(hash).op(OP_EQUAL).build(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy