public static void ValidateWitnessCommitment(this SlimBlock slimBlock) { var ser = slimBlock.Serialize(); Block block = Block.Load(ser, C.Network.Consensus.ConsensusFactory); if (!ByteArrays.AreAllBytesEqual(ser, block.ToBytes(C.ProtocolVersion))) { throw new InvalidOperationException("Serialization issue."); } // Validation for witness commitments. // * We compute the witness hash (which is the hash including witnesses) of all the block's transactions, except the // coinbase (where 0x0000....0000 is used instead). // * The coinbase scriptWitness is a stack of a single 32-byte vector, containing a witness nonce (unconstrained). // * We build a merkle tree with all those witness hashes as leaves (similar to the hashMerkleRoot in the block header). // * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are // {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness nonce). In case there are // multiple, the last one is used. bool fHaveWitness = false; Script commitment = GetWitnessCommitment(block); if (commitment != null) { uint256 hashWitness = BlockWitnessMerkleRoot(block, out bool _); // The malleation check is ignored; as the transaction tree itself // already does not permit it, it is impossible to trigger in the // witness tree. WitScript witness = block.Transactions[0].Inputs[0].WitScript; if ((witness.PushCount != 1) || (witness.Pushes.First().Length != 32)) { throw new InvalidOperationException("ConsensusErrors.BadWitnessNonceSize"); } var hashed = new byte[64]; Buffer.BlockCopy(hashWitness.ToBytes(), 0, hashed, 0, 32); Buffer.BlockCopy(witness.Pushes.First(), 0, hashed, 32, 32); hashWitness = Hashes.DoubleSHA256(hashed); // todo: not nice code to reuse tha variable if (!ByteArrays.AreAllBytesEqual(hashWitness.ToBytes(), commitment.ToBytes(true).Skip(6).ToArray())) { throw new InvalidOperationException("ConsensusErrors.BadWitnessMerkleMatch"); } fHaveWitness = true; } if (!fHaveWitness) { for (int i = 0; i < block.Transactions.Count; i++) { if (block.Transactions[i].HasWitness) { throw new InvalidOperationException("Unexpected witness."); } } } }
protected override void WorldPositionChanged(object source) { base.WorldPositionChanged(source); Vector3D worldPosition; SlimBlock.ComputeWorldCenter(out worldPosition); Vector3D diff = worldPosition - oldWorldPosition; double lengthSq = diff.LengthSquared(); if (lengthSq > MIN_MOVEMENT_SQUARED_FOR_UPDATE) { if (m_light != null) { m_light.MarkPropertiesDirty(); } } oldWorldPosition = worldPosition; if (m_oldWorldMatrix.Forward != WorldMatrix.Forward) { if (m_light != null) { m_light.MarkPropertiesDirty(); } } m_oldWorldMatrix = WorldMatrix; }
protected override void WorldPositionChanged(object source) { base.WorldPositionChanged(source); Vector3D worldPosition; SlimBlock.ComputeWorldCenter(out worldPosition); Vector3D diff = worldPosition - oldWorldPosition; double lengthSq = diff.LengthSquared(); if (lengthSq > MIN_MOVEMENT_SQUARED_FOR_UPDATE) { if (m_light != null && m_light.RenderObjectID != MyRenderProxy.RENDER_ID_UNASSIGNED) { m_light.MarkPositionDirty(); } } oldWorldPosition = worldPosition; if (m_oldWorldMatrix.Forward != WorldMatrix.Forward) { if (m_light != null && m_light.RenderObjectID != MyRenderProxy.RENDER_ID_UNASSIGNED) { m_light.MarkPositionDirty(); } } m_oldWorldMatrix = WorldMatrix; if (m_light != null && m_light.RenderObjectID != MyRenderProxy.RENDER_ID_UNASSIGNED) { m_light.UpdateLight(); } }
public static SlimBlock CreateTemplateBlock(this RPCBlockTemplate blockTemplate, uint time, bool isProofOfStake, Script scriptPubKey, Transaction coinstakeTransaction, Key blockSignatureKey) { if (!isProofOfStake && (scriptPubKey == null || coinstakeTransaction != null) || isProofOfStake && (scriptPubKey != null || coinstakeTransaction == null)) { throw new InvalidOperationException("Pow/pos parameter mismatch."); } var slimBlockHeader = blockTemplate.CreateSlimBlockHeader(isProofOfStake); slimBlockHeader.Timestamp = time; var slimBlock = new SlimBlock { IsProofOfStake = isProofOfStake, Height = blockTemplate.height, SlimBlockHeader = slimBlockHeader }; if (isProofOfStake) { slimBlock.AddPoSCoinbaseTransaction(); slimBlock.CoinstakeTransaction = coinstakeTransaction; } else { slimBlock.AddPoWCoinbaseTransaction(scriptPubKey, blockTemplate.coinbasevalue, blockTemplate.ExtraNonce); } slimBlock.SetPayloadTransactions(blockTemplate.transactions.Select(x => { var tx = C.Network.CreateTransaction(); tx.FromBytes(Encoders.Hex.DecodeData(x.data), C.ProtocolVersion); if (tx.GetHash() != uint256.Parse(x.txid)) { throw new InvalidOperationException(); } return(tx); })); slimBlock.CreateWitnessCommitment(); slimBlock.UpdateHeaderHashMerkleRoot(); slimBlock.SignBlock(blockSignatureKey); slimBlock.ValidateWitnessCommitment(); return(slimBlock); }
public static void SignBlock(this SlimBlock slimBlock, Key blockSignatureKey) { if (slimBlock.IsProofOfStake) { var headerBytes = slimBlock.SlimBlockHeader.SerializeTo80Bytes(); slimBlock.SlimBlockHeader.Data = headerBytes; // the Data field is used in serialization var headerHash = Hashes.DoubleSHA256(headerBytes); ECDSASignature signature = blockSignatureKey.Sign(headerHash); var blockSignature = new NBitcoin.Altcoins.X1Crypto.X1BlockSignature { Signature = signature.ToDER() }; slimBlock.SignatureBytes = blockSignature.ToBytes(); } else { slimBlock.SignatureBytes = new[] { (byte)0 }; // VarString with length of zero, zero encoded as as VarInt } }