public async Task GenerateConsensusTransactions_Failed() { TesterManager.InitialTesters(); //without public key { var input = new DPoSTriggerInformation { Behaviour = DPoSBehaviour.NextRound, InitialTermNumber = 1 }; var transactionResult = await TesterManager.Testers[0].ExecuteConsensusContractMethodWithMiningAsync( nameof(ConsensusContract.GenerateConsensusTransactions), input); transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); transactionResult.Error.Contains("Data to request consensus information should contain public key").ShouldBeTrue(); } //with random public key { var input = new DPoSTriggerInformation { PublicKey = ByteString.CopyFrom(CryptoHelpers.GenerateKeyPair().PublicKey), Behaviour = DPoSBehaviour.NextRound, RandomHash = Hash.Generate() }; await InitialConsensus_Success(); var transactionResult = await TesterManager.Testers[0].ExecuteConsensusContractMethodWithMiningAsync( nameof(ConsensusContract.GenerateConsensusTransactions), input); transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); transactionResult.Error.Contains("The given key was not present in the dictionary").ShouldBeTrue(); } }
public static async Task <DPoSHeaderInformation> GetInformationToUpdateConsensusAsync( this ContractTester <DPoSContractTestAElfModule> tester, DPoSTriggerInformation triggerInformation, DateTime dateTime) { var bytes = await tester.CallContractMethodAsync(tester.GetConsensusContractAddress(), ConsensusConsts.GetInformationToUpdateConsensus, triggerInformation, dateTime); return(DPoSHeaderInformation.Parser.ParseFrom(bytes)); }
public async Task GetInformationToUpdateConsensus_Failed() { TesterManager.InitialTesters(); //invalid public key { var input = new DPoSTriggerInformation { RandomHash = Hash.Generate(), Behaviour = DPoSBehaviour.NextRound }; var transactionResult = await TesterManager.Testers[0].ExecuteConsensusContractMethodWithMiningAsync( nameof(ConsensusContract.GetInformationToUpdateConsensus), input); transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); transactionResult.Error.Contains("Invalid public key").ShouldBeTrue(); } //invalid round info { var input = new DPoSTriggerInformation { Behaviour = DPoSBehaviour.UpdateValue, PublicKey = ByteString.CopyFromUtf8(TesterManager.Testers[0].PublicKey), }; var transactionResult = await TesterManager.Testers[0].ExecuteConsensusContractMethodWithMiningAsync( nameof(ConsensusContract.GetInformationToUpdateConsensus), input); transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); transactionResult.Error.Contains("Failed to get current round information").ShouldBeTrue(); } //valid data but random public key { var input = new DPoSTriggerInformation { Behaviour = DPoSBehaviour.UpdateValue, InitialTermNumber = 2, PreviousRandomHash = Hash.Generate(), PublicKey = ByteString.CopyFrom(CryptoHelpers.GenerateKeyPair().PublicKey), RandomHash = Hash.Generate() }; await InitialConsensus_Success(); var transactionResult = await TesterManager.Testers[0].ExecuteConsensusContractMethodWithMiningAsync( nameof(ConsensusContract.GetInformationToUpdateConsensus), input); transactionResult.Status.ShouldBe(TransactionResultStatus.Failed); transactionResult.Error.Contains("The given key was not present in the dictionary").ShouldBeTrue(); } }
public static async Task <List <Transaction> > GenerateConsensusTransactionsAsync( this ContractTester <DPoSContractTestAElfModule> tester, DPoSTriggerInformation triggerInformation) { var bytes = await tester.CallContractMethodAsync(tester.GetConsensusContractAddress(), ConsensusConsts.GenerateConsensusTransactions, triggerInformation); var txs = TransactionList.Parser.ParseFrom(bytes).Transactions.ToList(); tester.SignTransaction(ref txs, tester.KeyPair); tester.SupplyTransactionParameters(ref txs); return(txs); }
public static async Task <ConsensusCommand> GetConsensusCommandAsync( this ContractTester <DPoSSideChainTestAElfModule> tester, Timestamp timestamp = null) { var triggerInformation = new DPoSTriggerInformation { PublicKey = ByteString.CopyFrom(tester.KeyPair.PublicKey), }; var bytes = await tester.CallContractMethodAsync( tester.GetConsensusContractAddress(), // Usually the second contract is consensus contract. ConsensusConsts.GetConsensusCommand, triggerInformation); return(ConsensusCommand.Parser.ParseFrom(bytes)); }
public IMessage GetTriggerInformation(TriggerType triggerType) { if (triggerType == TriggerType.ConsensusCommand) { return(new CommandInput { PublicKey = PublicKey }); } if (_firstTriggerType == default) { _firstTriggerType = triggerType; } if (_controlInformation.ConsensusCommand == null) { return(new DPoSTriggerInformation { PublicKey = PublicKey, Behaviour = DPoSBehaviour.UpdateValue }); } if (Hint.Behaviour == DPoSBehaviour.UpdateValue || Hint.Behaviour == DPoSBehaviour.UpdateValueWithoutPreviousInValue) { var trigger = new DPoSTriggerInformation { PublicKey = PublicKey, RandomHash = RandomHash, PreviousRandomHash = _latestRandomHash, Behaviour = Hint.Behaviour }; if (triggerType != _firstTriggerType) { _latestRandomHash = RandomHash; } return(trigger); } return(new DPoSTriggerInformation { PublicKey = PublicKey, Behaviour = Hint.Behaviour }); }
public override TransactionList GenerateConsensusTransactions(DPoSTriggerInformation input) { // Some basic checks. Assert(input.PublicKey.Any(), "Data to request consensus information should contain public key."); var publicKey = input.PublicKey; var consensusInformation = GetInformationToUpdateConsensus(input); var round = consensusInformation.Round; var behaviour = consensusInformation.Behaviour; switch (behaviour) { case DPoSBehaviour.UpdateValueWithoutPreviousInValue: case DPoSBehaviour.UpdateValue: return(new TransactionList { Transactions = { GenerateTransaction(nameof(UpdateValue), round.ExtractInformationToUpdateConsensus(publicKey.ToHex()), input.PublicKey) } }); case DPoSBehaviour.NextRound: return(new TransactionList { Transactions = { GenerateTransaction(nameof(NextRound), round, input.PublicKey) } }); case DPoSBehaviour.NextTerm: return(new TransactionList { Transactions = { GenerateTransaction(nameof(NextTerm), round, input.PublicKey) } }); default: throw new ArgumentOutOfRangeException(); } }
public static async Task <Block> GenerateConsensusTransactionsAndMineABlockAsync( this ContractTester <DPoSContractTestAElfModule> tester, DPoSTriggerInformation triggerInformation, params ContractTester <DPoSContractTestAElfModule>[] testersGonnaExecuteThisBlock) { var bytes = await tester.CallContractMethodAsync(tester.GetConsensusContractAddress(), ConsensusConsts.GenerateConsensusTransactions, triggerInformation); var txs = TransactionList.Parser.ParseFrom(bytes).Transactions.ToList(); tester.SignTransaction(ref txs, tester.KeyPair); tester.SupplyTransactionParameters(ref txs); var block = await tester.MineAsync(txs); foreach (var contractTester in testersGonnaExecuteThisBlock) { await contractTester.ExecuteBlock(block, txs); } return(block); }
public override DPoSHeaderInformation GetInformationToUpdateConsensus(DPoSTriggerInformation input) { // Some basic checks. Assert(input.PublicKey.Any(), "Invalid public key."); var publicKey = input.PublicKey; var currentBlockTime = Context.CurrentBlockTime; var behaviour = input.Behaviour; Assert(TryToGetCurrentRoundInformation(out var currentRound), ContractErrorCode.GetErrorMessage(ContractErrorCode.AttemptFailed, "Failed to get current round information.")); switch (behaviour) { case DPoSBehaviour.UpdateValueWithoutPreviousInValue: case DPoSBehaviour.UpdateValue: Assert(input.RandomHash != null, "Random hash should not be null."); var inValue = currentRound.CalculateInValue(input.RandomHash); var outValue = Hash.FromMessage(inValue); var signature = Hash.FromTwoHashes(outValue, input.RandomHash); // Just initial signature value. var previousInValue = Hash.Empty; // Just initial previous in value. if (TryToGetPreviousRoundInformation(out var previousRound)) { signature = previousRound.CalculateSignature(inValue); LogVerbose($"Previous random hash: {input.PreviousRandomHash.ToHex()}"); if (input.PreviousRandomHash != Hash.Empty) { // If PreviousRandomHash is Hash.Empty, it means the sender unable or unwilling to publish his previous in value. previousInValue = previousRound.CalculateInValue(input.PreviousRandomHash); } } var updatedRound = currentRound.ApplyNormalConsensusData(publicKey.ToHex(), previousInValue, outValue, signature, currentBlockTime); ShareAndRecoverInValue(updatedRound, previousRound, inValue, publicKey.ToHex()); // To publish Out Value. return(new DPoSHeaderInformation { SenderPublicKey = publicKey, Round = updatedRound, Behaviour = behaviour, }); case DPoSBehaviour.NextRound: Assert( GenerateNextRoundInformation(currentRound, currentBlockTime, out var nextRound), "Failed to generate next round information."); nextRound.RealTimeMinersInformation[publicKey.ToHex()].ProducedBlocks += 1; Context.LogDebug(() => $"Mined blocks: {nextRound.GetMinedBlocks()}"); nextRound.ExtraBlockProducerOfPreviousRound = publicKey.ToHex(); return(new DPoSHeaderInformation { SenderPublicKey = publicKey, Round = nextRound, Behaviour = behaviour }); default: return(new DPoSHeaderInformation()); } }
public override void ConfigureServices(ServiceConfigurationContext context) { var services = context.Services; var ecKeyPair = CryptoHelpers.GenerateKeyPair(); var dposTriggerInformation = new DPoSTriggerInformation() { PublicKey = ByteString.CopyFrom(ecKeyPair.PublicKey), InitialTermNumber = 1, Behaviour = DPoSBehaviour.NextTerm }; services.AddTransient(o => { var mockService = new Mock <IConsensusInformationGenerationService>(); mockService.Setup(m => m.GetTriggerInformation(TriggerType.ConsensusTransactions)).Returns( dposTriggerInformation); mockService.Setup(m => m.GetTriggerInformation(TriggerType.BlockHeaderExtraData)).Returns( dposTriggerInformation); mockService.Setup(m => m.GetTriggerInformation(TriggerType.ConsensusCommand)).Returns( new CommandInput { PublicKey = ByteString.CopyFrom(ecKeyPair.PublicKey) }); mockService.Setup(m => m.ParseConsensusTriggerInformation(It.IsAny <byte[]>())).Returns( dposTriggerInformation); mockService.Setup(m => m.ExecuteContractAsync <ConsensusCommand>(It.IsAny <IChainContext>(), It.IsAny <string>(), It.IsAny <IMessage>(), It.IsAny <DateTime>())) .Returns(Task.FromResult(new ConsensusCommand { NextBlockMiningLeftMilliseconds = 4000, ExpectedMiningTime = DateTime.UtcNow.Add(TimeSpan.FromSeconds(4)).ToTimestamp() })); mockService.Setup(m => m.ExecuteContractAsync <ValidationResult>(It.IsAny <IChainContext>(), It.IsAny <string>(), It.IsAny <IMessage>(), It.IsAny <DateTime>())) .Returns(Task.FromResult(new ValidationResult { Success = true })); mockService.Setup(m => m.ExecuteContractAsync <TransactionList>(It.IsAny <IChainContext>(), It.IsAny <string>(), It.IsAny <IMessage>(), It.IsAny <DateTime>())) .Returns(Task.FromResult(new TransactionList { Transactions = { new Transaction { MethodName = ConsensusConsts.GenerateConsensusTransactions, Params = ByteString.CopyFromUtf8("test1") }, new Transaction { MethodName = ConsensusConsts.GenerateConsensusTransactions, Params = ByteString.CopyFromUtf8("test2") }, new Transaction { MethodName = ConsensusConsts.GenerateConsensusTransactions, Params = ByteString.CopyFromUtf8("test3") } } })); return(mockService.Object); }); services.AddTransient(o => { var mockService = new Mock <IAccountService>(); mockService.Setup(a => a.SignAsync(It.IsAny <byte[]>())).Returns <byte[]>(data => Task.FromResult(CryptoHelpers.SignWithPrivateKey(ecKeyPair.PrivateKey, data))); mockService.Setup(a => a.VerifySignatureAsync(It.IsAny <byte[]>(), It.IsAny <byte[]>(), It.IsAny <byte[]>() )).Returns <byte[], byte[], byte[]>((signature, data, publicKey) => { var recoverResult = CryptoHelpers.RecoverPublicKey(signature, data, out var recoverPublicKey); return(Task.FromResult(recoverResult && publicKey.BytesEqual(recoverPublicKey))); }); mockService.Setup(a => a.GetPublicKeyAsync()).ReturnsAsync(ecKeyPair.PublicKey); return(mockService.Object); }); services.AddTransient(o => { var mockService = new Mock <IConsensusScheduler>(); return(mockService.Object); }); services.AddTransient(o => { var mockService = new Mock <IBlockchainService>(); mockService.Setup(m => m.GetChainAsync()).Returns( Task.FromResult(new Chain() { BestChainHash = Hash.Empty, BestChainHeight = 100 })); return(mockService.Object); }); services.AddTransient <ConsensusControlInformation>(); services.AddTransient(o => { var mockService = new Mock <ISmartContractAddressService>(); mockService.Setup(m => m.GetAddressByContractName(It.IsAny <Hash>())).Returns( Address.Generate()); return(mockService.Object); }); services.AddTransient <IConsensusService, ConsensusService>(); services.AddTransient <ISystemTransactionGenerator, ConsensusTransactionGenerator>(); }