Beispiel #1
0
        public void Test_Tx_Pool_Replacement()
        {
            _blockManager.TryBuildGenesisBlock();
            TestTxPoolAdding();

            var privateKey = Crypto.GeneratePrivateKey().ToPrivateKey();
            var keyPair    = new EcdsaKeyPair(privateKey);

            AddRandomTxesToPool(keyPair, out var randomTxes);
            var rnd = new Random();

            randomTxes = randomTxes.OrderBy(item => rnd.Next()).ToList();
            bool useNewChainId = HardforkHeights.IsHardfork_9Active(_blockManager.GetHeight() + 1);
            var  signer        = new TransactionSigner();

            foreach (var tx in randomTxes)
            {
                Console.WriteLine($"nonce: {tx.Transaction.Nonce}");
                var newTx = new Transaction(tx.Transaction);
                // lower price
                newTx.GasPrice = tx.Transaction.GasPrice - 1;
                var randomTx = TestUtils.GetRandomTransaction(useNewChainId).Transaction;
                newTx.To       = randomTx.To;
                newTx.Value    = randomTx.Value;
                newTx.GasLimit = randomTx.GasLimit;
                var newTxReceipt = signer.Sign(newTx, keyPair, useNewChainId);
                var result       = _transactionPool.Add(newTxReceipt);
                Console.WriteLine($"old gas price: {tx.Transaction.GasPrice}, new gas price: {newTxReceipt.Transaction.GasPrice}");
                Assert.AreEqual(OperatingError.Underpriced, result);
                // equal price
                newTx.GasPrice = tx.Transaction.GasPrice;
                newTxReceipt   = signer.Sign(newTx, keyPair, useNewChainId);
                result         = _transactionPool.Add(newTxReceipt);
                Console.WriteLine($"old gas price: {tx.Transaction.GasPrice}, new gas price: {newTxReceipt.Transaction.GasPrice}");
                Assert.AreEqual(OperatingError.Underpriced, result);
                // higher price
                newTx.GasPrice = tx.Transaction.GasPrice + 1;
                newTxReceipt   = signer.Sign(newTx, keyPair, useNewChainId);
                result         = _transactionPool.Add(newTxReceipt);
                Console.WriteLine($"old gas price: {tx.Transaction.GasPrice}, new gas price: {newTxReceipt.Transaction.GasPrice}");
                Assert.AreEqual(OperatingError.DuplicatedTransaction, result);
                // higher price and all fields same
                newTx          = new Transaction(tx.Transaction);
                newTx.GasPrice = tx.Transaction.GasPrice + 1;
                newTxReceipt   = signer.Sign(newTx, keyPair, useNewChainId);
                result         = _transactionPool.Add(newTxReceipt);
                Console.WriteLine($"old gas price: {tx.Transaction.GasPrice}, new gas price: {newTxReceipt.Transaction.GasPrice}");
                Assert.AreEqual(OperatingError.Ok, result);
            }
        }
        private TransactionReceipt MakeNextValidatorsTxReceipt()
        {
            var sk = Crypto.GeneratePrivateKey();
            var pk = Crypto.ComputePublicKey(sk, false);
            var tx = _transactionBuilder.InvokeTransactionWithGasPrice(
                _wallet.EcdsaKeyPair.PublicKey.GetAddress(),
                ContractRegisterer.GovernanceContract,
                Money.Zero,
                GovernanceInterface.MethodChangeValidators,
                0,
                UInt256Utils.ToUInt256(GovernanceContract.GetCycleByBlockNumber(_stateManager.LastApprovedSnapshot.Blocks.GetTotalBlockHeight())),
                (pk)
                );
            var res = Signer.Sign(tx, _wallet.EcdsaKeyPair, true);

            Assert.False(_eventData.ContainsKey(res.Hash));
            _eventData.Add(res.Hash,
                           ByteString.CopyFrom(ContractEncoder.Encode(GovernanceInterface.EventChangeValidators, (pk))));
            return(res);
        }
Beispiel #3
0
        public void Test_Secp256K1EncryptDecryptRoundTrip()
        {
            var key      = Crypto.GeneratePrivateKey();
            var baseText =
                "0xf86d808504a817c800832dc6c0948e7b7262e0fa4616566591d51f998f16a79fb547880de0b6b3a76400008025a0115105d96a43f41a5ea562bb3e591cbfa431a8cdae9c3030457adca2cb854f78a012fb41922c53c73473563003667ed8e783359c91d95b42301e1955d530b1ca33"
                .HexToBytes();

            const int n       = 1000;
            var       startTs = TimeUtils.CurrentTimeMillis();

            for (var it = 0; it < n; ++it)
            {
                var plaintext = baseText.Concat(it.ToBytes()).ToArray();
                var cipher    = Crypto.Secp256K1Encrypt(key.ToPrivateKey().GetPublicKey().EncodeCompressed(), plaintext);
                var decrypted = Crypto.Secp256K1Decrypt(key, cipher);
                Assert.IsTrue(plaintext.SequenceEqual(decrypted));
            }

            var endTs = TimeUtils.CurrentTimeMillis();

            Console.WriteLine($"{n} encrypt/decrypt: {endTs - startTs}ms, avg = {(double) (endTs - startTs) / n}");
        }
        public void Test_InvalidValidatorKey()
        {
            var stateManager       = _container?.Resolve <IStateManager>();
            var contractRegisterer = _container?.Resolve <IContractRegisterer>();
            var tx       = new TransactionReceipt();
            var sender   = new BigInteger(0).ToUInt160();
            var context  = new InvocationContext(sender, stateManager !.LastApprovedSnapshot, tx);
            var contract = new GovernanceContract(context);
            var keyPair  = new EcdsaKeyPair(Crypto.GeneratePrivateKey().ToPrivateKey());

            ECDSAPublicKey[] allKeys = { keyPair.PublicKey };
            var          keygen      = new TrustlessKeygen(keyPair, allKeys, 0, 0);
            var          cycle       = 0.ToUInt256();
            ValueMessage value;

            // call ChangeValidators method with invalid key
            {
                byte[][] validators = { new byte[] { 0 } };
                var      input      = ContractEncoder.Encode(GovernanceInterface.MethodChangeValidators, cycle, validators);
                var      call       = contractRegisterer !.DecodeContract(context, ContractRegisterer.GovernanceContract, input);
                Assert.IsNotNull(call);
                var frame = new SystemContractExecutionFrame(call !, context, input, 100_000_000);
                Assert.AreEqual(ExecutionStatus.ExecutionHalted, contract.ChangeValidators(cycle, validators, frame));
            }

            // call commit
            {
                var      commitMessage = keygen.StartKeygen();
                byte[]   commitment    = commitMessage.Commitment.ToBytes();
                byte[][] encryptedRows = commitMessage.EncryptedRows;
                var      input         = ContractEncoder.Encode(GovernanceInterface.MethodKeygenCommit, cycle, commitment, encryptedRows);
                var      call          = contractRegisterer.DecodeContract(context, ContractRegisterer.GovernanceContract, input);
                Assert.IsNotNull(call);
                var frame = new SystemContractExecutionFrame(call !, context, input, 100_000_000);
                Assert.AreEqual(ExecutionStatus.ExecutionHalted, contract.KeyGenCommit(cycle, commitment, encryptedRows, frame));
                // set keygen state
                value = keygen.HandleCommit(0, commitMessage);
            }

            // send value
            {
                var proposer = new BigInteger(0).ToUInt256();
                var input    = ContractEncoder.Encode(GovernanceInterface.MethodKeygenSendValue, cycle, proposer, value.EncryptedValues);
                var call     = contractRegisterer.DecodeContract(context, ContractRegisterer.GovernanceContract, input);
                Assert.IsNotNull(call);
                var frame = new SystemContractExecutionFrame(call !, context, input, 100_000_000);
                Assert.AreEqual(ExecutionStatus.ExecutionHalted, contract.KeyGenSendValue(cycle, proposer, value.EncryptedValues, frame));
                // set keygen state
                Assert.IsTrue(keygen.HandleSendValue(0, value));
                Assert.IsTrue(keygen.Finished());
            }

            // confirm
            {
                ThresholdKeyring?keyring = keygen.TryGetKeys();
                Assert.IsNotNull(keyring);
                var input = ContractEncoder.Encode(GovernanceInterface.MethodKeygenConfirm, cycle,
                                                   keyring !.Value.TpkePublicKey.ToBytes(),
                                                   keyring !.Value.ThresholdSignaturePublicKeySet.Keys.Select(key => key.ToBytes()).ToArray());
                var call = contractRegisterer.DecodeContract(context, ContractRegisterer.GovernanceContract, input);
                Assert.IsNotNull(call);
                var frame = new SystemContractExecutionFrame(call !, context, input, 100_000_000);
                Assert.AreEqual(ExecutionStatus.Ok, contract.KeyGenConfirm(cycle, keyring !.Value.TpkePublicKey.ToBytes(),
                                                                           keyring !.Value.ThresholdSignaturePublicKeySet.Keys.Select(key => key.ToBytes()).ToArray(), frame));
                // set keygen state
                Assert.IsTrue(keygen.HandleConfirm(keyring !.Value.TpkePublicKey,
                                                   keyring !.Value.ThresholdSignaturePublicKeySet));
            }

            // check no validators in storage
            Assert.Throws <ConsensusStateNotPresentException>(() => context.Snapshot.Validators.GetValidatorsPublicKeys());

            // finish cycle
            {
                var input = ContractEncoder.Encode(GovernanceInterface.MethodFinishCycle, cycle);
                var call  = contractRegisterer.DecodeContract(context, ContractRegisterer.GovernanceContract, input);
                Assert.IsNotNull(call);
                var frame = new SystemContractExecutionFrame(call !, context, input, 100_000_000);
                // set next cycle block number in frame:
                frame.InvocationContext.Receipt.Block = StakingContract.CycleDuration;
                Assert.AreEqual(ExecutionStatus.Ok, contract.FinishCycle(cycle, frame));
            }

            // check no validators in storage again
            Assert.IsEmpty(context.Snapshot.Validators.GetValidatorsPublicKeys());
        }
Beispiel #5
0
        private static ThresholdKeyring[] SimulateKeygen(int n, int f, DeliveryServiceMode mode)
        {
            var ecdsaKeys = Enumerable.Range(0, n)
                            .Select(_ => Crypto.GeneratePrivateKey())
                            .Select(x => x.ToPrivateKey())
                            .Select(x => new EcdsaKeyPair(x))
                            .ToArray();

            var keyGens = Enumerable.Range(0, n)
                          .Select(i => new TrustlessKeygen(ecdsaKeys[i], ecdsaKeys.Select(x => x.PublicKey), f, 0))
                          .ToArray();


            var messageLedger = new RandomSamplingQueue <QueueItem>();

            messageLedger.Enqueue(new QueueItem(-1, null));

            var curKeys = keyGens.Select(_ => (ThresholdKeyring?)null).ToArray();

            while (messageLedger.Count > 0)
            {
                QueueItem?msg;
                var       success = mode switch
                {
                    DeliveryServiceMode.TAKE_FIRST => messageLedger.TryDequeue(out msg),
                    DeliveryServiceMode.TAKE_LAST => messageLedger.TryTakeLast(out msg),
                    DeliveryServiceMode.TAKE_RANDOM => messageLedger.TrySample(out msg),
                    _ => throw new NotImplementedException($"Unknown mode {mode}")
                };
                Assert.IsTrue(success);
                switch (msg?.payload)
                {
                case null:
                    for (var i = 0; i < n; ++i)
                    {
                        messageLedger.Enqueue(new QueueItem(i, keyGens[i].StartKeygen()));
                    }
                    break;

                case CommitMessage commitMessage:
                    for (var i = 0; i < n; ++i)
                    {
                        messageLedger.Enqueue(new QueueItem(i, keyGens[i].HandleCommit(msg.sender, commitMessage)));
                    }
                    break;

                case ValueMessage valueMessage:
                    for (var i = 0; i < n; ++i)
                    {
                        keyGens[i].HandleSendValue(msg.sender, valueMessage);
                    }
                    break;

                default:
                    Assert.Fail($"Message of type {msg.GetType()} occurred");
                    break;
                }

                for (var i = 0; i < n; ++i)
                {
                    var curKey = keyGens[i].TryGetKeys();
                    if (curKey is null)
                    {
                        Assert.AreEqual(null, curKeys[i]);
                        continue;
                    }

                    if (!curKeys[i].HasValue)
                    {
                        curKeys[i] = curKey;
                        continue;
                    }

                    Assert.IsTrue(curKey.Value.TpkePrivateKey.ToBytes()
                                  .SequenceEqual(curKeys[i] !.Value.TpkePrivateKey.ToBytes()));
                    Assert.AreEqual(curKey.Value.PublicPartHash(), curKeys[i] !.Value.PublicPartHash());
                }

                for (var i = 0; i < n; ++i)
                {
                    keyGens[i] = TestSerializationRoundTrip(keyGens[i], ecdsaKeys[i]);
                }
            }

            for (var i = 0; i < n; ++i)
            {
                Assert.IsTrue(keyGens[i].Finished());
                Assert.AreNotEqual(curKeys[i], null);
            }

            var keys = keyGens
                       .Select(x => x.TryGetKeys() ?? throw new Exception())
                       .ToArray();

            for (var i = 0; i < n; ++i)
            {
                Assert.AreEqual(keys[0].TpkePublicKey, keys[i].TpkePublicKey);
                Assert.AreEqual(keys[0].ThresholdSignaturePublicKeySet, keys[i].ThresholdSignaturePublicKeySet);
            }

            return(keys);
        }