public void QuickTestsOnKeyIdBytes() { var a = new KeyId("93e5d305cad2588d5fb254065fe48ce446028ba3"); var b = new ScriptId("93e5d305cad2588d5fb254065fe48ce446028ba3"); var b2 = new WitKeyId("93e5d305cad2588d5fb254065fe48ce446028ba3"); Assert.Equal(a.ToString(), b.ToString()); Assert.Equal(a.ToString(), b2.ToString()); Assert.Equal("93e5d305cad2588d5fb254065fe48ce446028ba3", a.ToString()); var bytes = Encoders.Hex.DecodeData("93e5d305cad2588d5fb254065fe48ce446028ba3"); Assert.True(StructuralComparisons.StructuralComparer.Compare(a.ToBytes(), b.ToBytes()) == 0); Assert.True(StructuralComparisons.StructuralComparer.Compare(b2.ToBytes(), b.ToBytes()) == 0); var c = new KeyId(bytes); var d = new ScriptId(bytes); var d2 = new WitKeyId(bytes); Assert.Equal(a, c); Assert.Equal(d, b); Assert.Equal(b2, d2); Assert.Equal(c.ToString(), d.ToString()); Assert.Equal(c.ToString(), d2.ToString()); Assert.Equal("93e5d305cad2588d5fb254065fe48ce446028ba3", c.ToString()); Assert.True(StructuralComparisons.StructuralComparer.Compare(c.ToBytes(), d.ToBytes()) == 0); Assert.True(StructuralComparisons.StructuralComparer.Compare(c.ToBytes(), d2.ToBytes()) == 0); var e = new WitScriptId("93e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd10550089"); Assert.Equal("93e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd10550089", e.ToString()); bytes = Encoders.Hex.DecodeData("93e5d305cad2588d5fb254065fe48ce446028ba380e6ee663baea9cd10550089"); var e2 = new WitScriptId(bytes); Assert.Equal(e, e2); }
public Script GenerateScriptPubKey(KeyId pubkeyHash) { return(new Script( OpcodeType.OP_DUP, OpcodeType.OP_HASH160, Op.GetPushOp(pubkeyHash.ToBytes()), OpcodeType.OP_EQUALVERIFY, OpcodeType.OP_CHECKSIG )); }
public static void CheckTransaction(IStateRepositoryRoot stateRepositoryRoot, Transaction transaction) { foreach (TxOut output in transaction.Outputs) { if (PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(output.ScriptPubKey)) { KeyId p2pkhParams = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(output.ScriptPubKey); var to = new uint160(p2pkhParams.ToBytes()); if (stateRepositoryRoot.GetAccountState(to) != null) { new ConsensusError("p2pkh-to-contract", "attempted send directly to contract address. use OP_CALL instead.").Throw(); } } } }
private void CheckTransaction(Transaction transaction) { foreach (TxOut output in transaction.Outputs) { if (PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(output.ScriptPubKey)) { KeyId p2pkhParams = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(output.ScriptPubKey); uint160 to = new uint160(p2pkhParams.ToBytes()); if (this.ContractCoinviewRule.OriginalStateRoot.GetAccountState(to) != null) { new ConsensusError("p2pkh-to-contract", "attempted send directly to contract address. use OP_CALL instead.").Throw(); } } } }
public void ReadWrite(BitcoinStream stream) { if (stream.Serializing) { var ms = new MemoryStream(); var bs = new BitcoinStream(ms, true) { Type = SerializationType.Hash }; if (KeyId != null) { stream.ReadWrite(new uint160(KeyId.ToBytes())); } else { bs.ReadWriteAsCompactVarInt(ref Height); bs.ReadWriteAsCompactVarInt(ref Index); } var packBytes = ms.ToArray(); stream.ReadWriteAsVarString(ref packBytes); } else { var packVar = new VarString(); stream.ReadWrite(ref packVar); var bs = new BitcoinStream(packVar.GetString()); if (packVar.Length >= 20) { var keyHash = uint160.Zero; stream.ReadWrite(ref keyHash); KeyId = new KeyId(keyHash); } else { bs.ReadWriteAsCompactVarInt(ref Height); bs.ReadWriteAsCompactVarInt(ref Index); } } }
/// <summary> /// Creates a cold staking script. /// </summary> /// <remarks>Two keys control the balance associated with the script. /// The hot wallet key allows transactions to only spend amounts back to themselves while the cold /// wallet key allows amounts to be moved to different addresses. This makes it possible to perform /// staking using the hot wallet key so that even if the key becomes compromised it can't be used /// to reduce the balance. Only the person with the cold wallet key can retrieve the coins and move /// them elsewhere. This behavior is enforced by the <see cref="OP_CHECKCOLDSTAKEVERIFY"/> /// opcode within the script flow related to hot wallet key usage. It sets the <see cref="PosTransaction.IsColdCoinStake"/> /// flag if the transaction spending an output, which contains this instruction, is a coinstake /// transaction. If this flag is set then further rules are enforced by <see cref="Stratis.Bitcoin.Features.Consensus.Rules.CommonRules.PosColdStakingRule"/>. /// </remarks> /// <param name="hotPubKeyHash">The hot wallet public key hash to use.</param> /// <param name="coldPubKeyHash">The cold wallet public key hash to use.</param> /// <returns>The cold staking script.</returns> /// <seealso cref="Consensus.Rules.CommonRules.PosColdStakingRule"/> public Script GenerateScriptPubKey(KeyId hotPubKeyHash, KeyId coldPubKeyHash) { // The initial stack consumed by this script will be set up differently depending on whether a // hot or cold pubkey is used - i.e. either <scriptSig> 0 <coldPubKey> OR <scriptSig> 1 <hotPubKey>. return(new Script( // Duplicates the last stack entry resulting in: // <scriptSig> 0/1 <coldPubKey/hotPubKey> <coldPubKey/hotPubKey>. #pragma warning disable SA1114 // Parameter list must follow declaration OP_DUP, #pragma warning restore SA1114 // Parameter list must follow declaration // Replaces the last stack entry with its hash resulting in: // <scriptSig> 0/1 <coldPubKey/hotPubKey> <coldPubKeyHash/hotPubKeyHash>. OP_HASH160, // Rotates the top 3 stack entries resulting in: // <scriptSig> <coldPubKey/hotPubKey> <coldPubKeyHash/hotPubKeyHash> 0/1. OP_ROT, // Consumes the top stack entry and continues from the OP_ELSE if the value was 0. Results in: // <scriptSig> <coldPubKey/hotPubKey> <coldPubKeyHash/hotPubKeyHash>. OP_IF, // Reaching this point means that the value was 1 - i.e. the hotPubKey is being used. // Executes the opcode as described in the remarks section. Stack remains unchanged. OP_CHECKCOLDSTAKEVERIFY, // Pushes the expected hotPubKey value onto the stack for later comparison purposes. Results in: // <scriptSig> <hotPubKey> <hotPubKeyHash> <hotPubKeyHash for comparison>. Op.GetPushOp(hotPubKeyHash.ToBytes()), // The code contained in the OP_ELSE is executed when the value was 0 - i.e. the coldPubKey is used. OP_ELSE, // Pushes the expected coldPubKey value onto the stack for later comparison purposes. Results in: // <scriptSig> <coldPubKey> <coldPubKeyHash> <coldPubKeyHash for comparison>. Op.GetPushOp(coldPubKeyHash.ToBytes()), OP_ENDIF, // Checks that the <coldPubKeyHash/hotPubKeyHash> matches the comparison value and removes both values // from the stack. The script fails at this point if the values mismatch. Results in: // <scriptSig> <coldPubKey/hotPubKey>. OP_EQUALVERIFY, // Consumes the top 2 stack entries and uses those values to verify the signature. Results in: // true/false - i.e. true if the signature is valid and false otherwise. OP_CHECKSIG)); }
public AccountRestrictedKeyId(KeyId keyId, int accountId) : this(keyId.ToBytes(), accountId) { }