public bool Sign(ContractParametersContext context) { bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { WalletAccount account = GetAccount(scriptHash); if (account?.HasKey != true) { continue; } KeyPair key = account.GetKey(); byte[] signature = context.Verifiable.Sign(key); fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); } return(fSuccess); }
public Block CreateBlock() { Contract contract = Contract.CreateMultiSigContract(M, Validators); ContractParametersContext sc = new ContractParametersContext(Block); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { if (CommitPayloads[i]?.ConsensusMessage.ViewNumber != ViewNumber) { continue; } sc.AddSignature(contract, Validators[i], CommitPayloads[i].GetDeserializedMessage <Commit>().Signature); j++; } Block.Witness = sc.GetWitnesses()[0]; Block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray(); return(Block); }
/// <summary> /// 交易签名 /// AddCode /// </summary> /// <param name="context">交易上下文</param> /// <param name="privatekey">私钥</param> /// <returns>结果</returns> public bool Sign(ContractParametersContext context, string privatekey) { bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { WalletAccount account = GetAccount(scriptHash); //if (account?.HasKey != true) continue; // 判断账号是否有nep2key 只读私有属性 只能通过构造函数赋值 所以不伪造 // 使用私钥生成钥匙 KeyPair key = new KeyPair(privatekey.HexToBytes()); byte[] signature = context.Verifiable.Sign(key); //key.PrivateKey.ToHexString(); //key.PublicKey.EncodePoint(true).ToHexString(); //File.AppendAllText("wallet.log", $"privatekey: {key.PrivateKey.ToHexString()} \n publickey: {key.PublicKey.EncodePoint(true).ToHexString()}\n"); fSuccess |= context.AddSignature(account.Contract, key.PublicKey, signature); } return(fSuccess); }
public static Block CreateSignedBlock(Header prevHeader, IReadOnlyList <KeyPair> keyPairs, uint network, Transaction[]?transactions = null, ulong timestamp = 0) { transactions ??= Array.Empty <Transaction>(); var blockHeight = prevHeader.Index + 1; var block = new Block { Header = new Header { Version = 0, PrevHash = prevHeader.Hash, MerkleRoot = MerkleTree.ComputeRoot(transactions.Select(t => t.Hash).ToArray()), Timestamp = timestamp > prevHeader.Timestamp ? timestamp : Math.Max(Neo.Helper.ToTimestampMS(DateTime.UtcNow), prevHeader.Timestamp + 1), Index = blockHeight, PrimaryIndex = 0, NextConsensus = prevHeader.NextConsensus }, Transactions = transactions }; // generate the block header witness. Logic lifted from ConsensusContext.CreateBlock var m = keyPairs.Count - (keyPairs.Count - 1) / 3; var contract = Contract.CreateMultiSigContract(m, keyPairs.Select(k => k.PublicKey).ToList()); var signingContext = new ContractParametersContext(null, new BlockScriptHashes(prevHeader.NextConsensus), network); for (int i = 0; i < keyPairs.Count; i++) { var signature = block.Header.Sign(keyPairs[i], network); signingContext.AddSignature(contract, keyPairs[i].PublicKey, signature); if (signingContext.Completed) { break; } } if (!signingContext.Completed) { throw new Exception("block signing incomplete"); } block.Header.Witness = signingContext.GetWitnesses()[0]; return(block); }
public Block CreateBlock() { EnsureHeader(); Contract contract = Contract.CreateMultiSigContract(M, Validators); ContractParametersContext sc = new ContractParametersContext(DBFTPlugin.System.StoreView, Block.Header); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { if (GetMessage(CommitPayloads[i])?.ViewNumber != ViewNumber) { continue; } sc.AddSignature(contract, Validators[i], GetMessage <Commit>(CommitPayloads[i]).Signature); j++; } Block.Header.Witness = sc.GetWitnesses()[0]; Block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray(); return(Block); }
public bool Sign(ContractParametersContext context) { bool fSuccess = false; foreach (UInt160 scriptHash in context.ScriptHashes) { VerificationContract contract = GetContract(scriptHash); if (contract == null) { continue; } KeyPair key = GetKeyByScriptHash(scriptHash); if (key == null) { continue; } byte[] signature = context.Verifiable.Sign(key); fSuccess |= context.AddSignature(contract, key.PublicKey, signature); } return(fSuccess); }
/// <summary> /// Verify Witness count and add witnesses /// </summary> public async Task <Transaction> SignAsync() { // Calculate NetworkFee Tx.Witnesses = Tx.GetScriptHashesForVerifying(null).Select(u => new Witness() { InvocationScript = Array.Empty <byte>(), VerificationScript = GetVerificationScript(u) }).ToArray(); Tx.NetworkFee = await rpcClient.CalculateNetworkFeeAsync(Tx).ConfigureAwait(false); Tx.Witnesses = null; var gasBalance = await new Nep17API(rpcClient).BalanceOfAsync(NativeContract.GAS.Hash, Tx.Sender).ConfigureAwait(false); if (gasBalance < Tx.SystemFee + Tx.NetworkFee) { throw new InvalidOperationException($"Insufficient GAS in address: {Tx.Sender.ToAddress(rpcClient.protocolSettings.AddressVersion)}"); } // Sign with signStore for (int i = 0; i < signStore.Count; i++) { foreach (var key in signStore[i].KeyPairs) { byte[] signature = Tx.Sign(key, rpcClient.protocolSettings.Network); if (!context.AddSignature(signStore[i].Contract, key.PublicKey, signature)) { throw new Exception("AddSignature failed!"); } } } // Verify witness count if (!context.Completed) { throw new Exception($"Please add signature or witness first!"); } Tx.Witnesses = context.GetWitnesses(); return(Tx); }
public Block CreateBlock() { Block block = MakeHeader(); if (block == null) { return(null); } Contract contract = Contract.CreateMultiSigContract(M, Validators); ContractParametersContext sc = new ContractParametersContext(block); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { if (Signatures[i] != null) { sc.AddSignature(contract, Validators[i], Signatures[i]); j++; } } sc.Verifiable.Witnesses = sc.GetWitnesses(); block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray(); return(block); }
private void CheckSignatures() { if (context.Signatures.Count(p => p != null) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) { Contract contract = Contract.CreateMultiSigContract(context.M, context.Validators); Block block = context.MakeHeader(); ContractParametersContext sc = new ContractParametersContext(block); for (int i = 0, j = 0; i < context.Validators.Length && j < context.M; i++) { if (context.Signatures[i] != null) { sc.AddSignature(contract, context.Validators[i], context.Signatures[i]); j++; } } sc.Verifiable.Witnesses = sc.GetWitnesses(); block.Transactions = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray(); Log($"relay block: {block.Hash}"); system.LocalNode.Tell(new LocalNode.Relay { Inventory = block }); context.State |= ConsensusState.BlockSent; } }
// Since ConensusContext's constructor is internal, it can't be used from neo-express. // CreatePreloadBlock replicates the following logic for creating an empty block with ConensusContext // var ctx = new Neo.Consensus.ConsensusContext(wallet, store); // ctx.Reset(0); // ctx.MakePrepareRequest(); // ctx.MakeCommit(); // ctx.Save(); // Block block = ctx.CreateBlock(); static Block CreatePreloadBlock(Neo.Wallets.Wallet wallet, Random random, Transaction?transaction = null) { using var snapshot = Blockchain.Singleton.GetSnapshot(); var validators = snapshot.GetValidators(); if (validators.Length != 1) { throw new InvalidOperationException("Preload only supported for single-node blockchains"); } var amountNetFee = Block.CalculateNetFee(Enumerable.Empty <Transaction>()); if (amountNetFee != Fixed8.Zero) { throw new InvalidOperationException("amountNetFee must be zero"); } var keyPair = wallet.GetAccount(validators[0]).GetKey(); var prevHash = snapshot.CurrentBlockHash; var prevBlock = snapshot.GetBlock(prevHash); var nonce = NextNonce(random); var minerTx = new MinerTransaction { Nonce = (uint)(nonce % (uint.MaxValue + 1ul)), Attributes = Array.Empty <TransactionAttribute>(), Inputs = Array.Empty <CoinReference>(), Outputs = Array.Empty <TransactionOutput>(), Witnesses = Array.Empty <Witness>() }; var blockTransactions = transaction == null ? new Transaction[] { minerTx } : new Transaction[] { minerTx, transaction }; var txHashes = blockTransactions.Select(tx => tx.Hash).ToArray(); var merkleRoot = MerkleTree.ComputeRoot(txHashes); var nextConsensus = Blockchain.GetConsensusAddress(snapshot.GetValidators(blockTransactions).ToArray()); var consensusData = nonce; var block = new Block() { Version = 0, PrevHash = prevHash, MerkleRoot = merkleRoot, Timestamp = prevBlock.Timestamp + 1, Index = prevBlock.Index + 1, ConsensusData = nonce, NextConsensus = nextConsensus, Transactions = Array.Empty <Transaction>(), }; var commit = new Neo.Consensus.Commit() { ViewNumber = 0, Signature = block.Sign(keyPair) }; var payload = new ConsensusPayload { Version = 0, PrevHash = prevHash, BlockIndex = block.Index, ValidatorIndex = (ushort)0, Data = Neo.IO.Helper.ToArray(commit) }; { var sc = new ContractParametersContext(payload); wallet.Sign(sc); payload.Witness = sc.GetWitnesses()[0]; } { var m = validators.Length - ((validators.Length - 1) / 3); Contract contract = Contract.CreateMultiSigContract(m, validators); ContractParametersContext sc = new ContractParametersContext(block); for (int i = 0, j = 0; i < validators.Length && j < m; i++) { sc.AddSignature(contract, validators[0], payload.GetDeserializedMessage <Neo.Consensus.Commit>().Signature); j++; } block.Witness = sc.GetWitnesses()[0]; block.Transactions = blockTransactions; } return(block); }
Block CreateSignedBlock(Transaction[] transactions) { // The logic in this method is distilled from ConsensusService/ConsensusContext + MemPool tx verification logic var snapshot = neoSystem.StoreView; // Verify the provided transactions. When running, Blockchain class does verification in two steps: VerifyStateIndependent and VerifyStateDependent. // However, Verify does both parts and there's no point in verifying dependent/independent in separate steps here var verificationContext = new TransactionVerificationContext(); for (int i = 0; i < transactions.Length; i++) { var q = transactions[i].Size * NativeContract.Policy.GetFeePerByte(snapshot); if (transactions[i].Verify(ProtocolSettings, snapshot, verificationContext) != VerifyResult.Succeed) { throw new Exception("Verification failed"); } } // create the block instance var prevHash = NativeContract.Ledger.CurrentHash(snapshot); var prevBlock = NativeContract.Ledger.GetHeader(snapshot, prevHash); var blockHeight = prevBlock.Index + 1; var block = new Block { Header = new Header { Version = 0, PrevHash = prevHash, MerkleRoot = MerkleTree.ComputeRoot(transactions.Select(t => t.Hash).ToArray()), Timestamp = Math.Max(Neo.Helper.ToTimestampMS(DateTime.UtcNow), prevBlock.Timestamp + 1), Index = blockHeight, PrimaryIndex = 0, NextConsensus = Contract.GetBFTAddress( NeoToken.ShouldRefreshCommittee(blockHeight, ProtocolSettings.CommitteeMembersCount) ? NativeContract.NEO.ComputeNextBlockValidators(snapshot, ProtocolSettings) : NativeContract.NEO.GetNextBlockValidators(snapshot, ProtocolSettings.ValidatorsCount)), }, Transactions = transactions }; // retrieve the validators for the next block. Logic lifted from ConensusContext.Reset var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, ProtocolSettings.ValidatorsCount); var m = validators.Length - (validators.Length - 1) / 3; // generate the block header witness. Logic lifted from ConsensusContext.CreateBlock var contract = Contract.CreateMultiSigContract(m, validators); var signingContext = new ContractParametersContext(snapshot, block.Header, ProtocolSettings.Network); for (int i = 0, j = 0; i < validators.Length && j < m; i++) { var key = consensusNodesKeys.Value.SingleOrDefault(k => k.PublicKey.Equals(validators[i])); if (key == null) { continue; } var signature = block.Header.Sign(key, ProtocolSettings.Network); signingContext.AddSignature(contract, validators[i], signature); j++; } if (!signingContext.Completed) { throw new Exception("block signing incomplete"); } block.Header.Witness = signingContext.GetWitnesses()[0]; return(block); }