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); }
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()); }
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); }