Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        /// <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);
        }
Пример #8
0
        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);
        }
Пример #9
0
 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;
     }
 }
Пример #10
0
        // 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);
        }
Пример #11
0
        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);
        }