public void ContractTransaction_MethodDoesntExist() { // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/EmptyContract.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.node1.WaitMempoolCount(1); this.node1.WaitForBlocksToBeMined(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); double amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction("MethodThatDoesntExist", preResponse.NewContractAddress, amount); this.node2.WaitMempoolCount(1); this.node2.WaitForBlocksToBeMined(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; Assert.Single(refundTransaction.Outputs); // No transfers persisted uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); Money fee = lastBlock.Transactions[0].Outputs[0].Value - new Money(50, MoneyUnit.BTC); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.Equal(GasPriceList.BaseCost, receipt.GasUsed); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Equal(ContractInvocationErrors.MethodDoesNotExist, receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public void ContractTransaction_RecursiveContractCall_OutOfGas() { // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/RecursiveLoopCall.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.node1.WaitMempoolCount(1); this.node1.WaitForBlocksToBeMined(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); double amount = 25; ulong gasLimit = SmartContractFormatRule.GasLimitMaximum; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction(nameof(RecursiveLoopCall.Call), preResponse.NewContractAddress, amount, gasLimit: gasLimit); this.node2.WaitMempoolCount(1); this.node2.WaitForBlocksToBeMined(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; Assert.Single(refundTransaction.Outputs); // No transfers persisted uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.True(receipt.GasUsed > (gasLimit - GasPriceList.BaseCost)); // The amount spent should be within 1 BaseCost of being used up. Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.StartsWith("Stratis.SmartContracts.SmartContractAssertException", receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public void ContractTransaction_MemoryLimit() { // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/MemoryConsumingContract.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; uint256 currentHash = this.node1.GetLastBlock().GetHash(); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Int, 100001) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction("UseTooMuchMemory", preResponse.NewContractAddress, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; Assert.Single(refundTransaction.Outputs); // No transfers persisted uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); Money fee = lastBlock.Transactions[0].Outputs[0].Value - new Money(50, MoneyUnit.BTC); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.True(GasPriceList.BaseCost < receipt.GasUsed); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.StartsWith($"{typeof(RuntimeObserver.MemoryConsumptionException).FullName}", receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public void ContractTransaction_ValidationFailure() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Create transaction with non-deterministic bytecode. ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/NonDeterministicContract.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract wasn't created Assert.Null(this.node2.GetCode(response.NewContractAddress)); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.Equal(GasPriceList.CreateCost, receipt.GasUsed); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.To); }
public void ContractTransaction_InvalidByteCode() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); double amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Create transaction with random bytecode. var random = new Random(); byte[] bytes = new byte[100]; random.NextBytes(bytes); BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(bytes, amount); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract wasn't created Assert.Null(this.node1.GetCode(response.NewContractAddress)); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.Equal(GasPriceList.CreateCost, receipt.GasUsed); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.To); }
public void ContractTransaction_Call_Method_Consumes_All_Gas_Throws_OutOfGasException() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/InfiniteLoop.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 0; ulong gasLimit = SmartContractFormatLogic.GasLimitCallMinimum + 1; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction(nameof(InfiniteLoop.Loop), preResponse.NewContractAddress, amount, gasLimit: gasLimit, gasPrice: 200); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block does not contain a refund transaction Assert.Equal(2, lastBlock.Transactions.Count); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.Equal(gasLimit, receipt.GasUsed); // All the gas should have been consumed Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.StartsWith("Execution ran out of gas.", receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public void ContractTransaction_RecursiveContractCreate_OutOfGas() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); decimal amount = 25; ulong gasLimit = SmartContractFormatLogic.GasLimitMaximum; uint256 currentHash = this.node1.GetLastBlock().GetHash(); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/RecursiveLoopCreate.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount, gasLimit: gasLimit); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract was not created Assert.Null(this.node2.GetCode(response.NewContractAddress)); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.True(receipt.GasUsed > (gasLimit - GasPriceList.BaseCost)); // The amount spent should be within 1 BaseCost of being used up. Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.To); }
public void ContractTransaction_AddressDoesntExist() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); double amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send call to non-existent address string nonExistentAddress = new uint160(0).ToBase58Address(this.node1.CoreNode.FullNode.Network); Assert.Null(this.node1.GetCode(nonExistentAddress)); BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction("Method", nonExistentAddress, amount); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; Assert.Single(refundTransaction.Outputs); // No transfers uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.Equal(GasPriceList.BaseCost, receipt.GasUsed); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Equal(StateTransitionErrors.NoCode, receipt.Error); Assert.Equal(nonExistentAddress, receipt.To); }
public void Local_Call_At_Height() { // Demonstrates some potentially unusual behaviour when saving contract state. var localExecutor = this.mockChain.Nodes[0].CoreNode.FullNode.NodeService <ILocalExecutor>(); // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/StorageDemo.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); uint256 currentHash = this.node1.GetLastBlock().GetHash(); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); ReceiptResponse receipt = this.node1.GetReceipt(preResponse.TransactionId.ToString()); Assert.True(receipt.Success); // Get initial state at height var call = new ContractTxData(1, 100, (Gas)250000, preResponse.NewContractAddress.ToUint160(this.node1.CoreNode.FullNode.Network), nameof(StorageDemo.GetCounterValue)); var initialState = localExecutor.Execute((ulong)this.node1.CoreNode.FullNode.ChainIndexer.Height, this.mockChain.Nodes[0].MinerAddress.Address.ToUint160(this.node1.CoreNode.FullNode.Network), 0, call); Assert.Equal(12345, (int)initialState.Return); // Call Counter() and confirm that it succeeds BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(StorageDemo.Increment), preResponse.NewContractAddress, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Get local state at height 2 after calling counter initialState = localExecutor.Execute((ulong)this.node1.CoreNode.FullNode.ChainIndexer.Height, this.mockChain.Nodes[0].MinerAddress.Address.ToUint160(this.node1.CoreNode.FullNode.Network), 0, call); Assert.Equal(12346, (int)initialState.Return); // Get local state at previous height before calling counter initialState = localExecutor.Execute((ulong)this.node1.CoreNode.FullNode.ChainIndexer.Height - 1, this.mockChain.Nodes[0].MinerAddress.Address.ToUint160(this.node1.CoreNode.FullNode.Network), 0, call); Assert.Equal(12345, (int)initialState.Return); }
public void InternalTransfer_BetweenContracts() { // Deploy contract to send to ContractCompilationResult receiveCompilationResult = ContractCompiler.CompileFile("SmartContracts/NestedCallsReceiver.cs"); Assert.True(receiveCompilationResult.Success); BuildCreateContractTransactionResponse receiveResponse = this.node1.SendCreateContractTransaction(receiveCompilationResult.Compilation, 0); this.node1.WaitMempoolCount(1); this.node1.WaitForBlocksToBeMined(1); Assert.NotNull(this.node1.GetCode(receiveResponse.NewContractAddress)); // Deploy contract to send from ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/NestedCallsStarter.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.node1.WaitMempoolCount(1); this.node1.WaitForBlocksToBeMined(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); double amount = 25; uint256 currentHash = this.node1.GetLastBlock().GetHash(); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, receiveResponse.NewContractAddress) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction(nameof(NestedCallsStarter.Start), preResponse.NewContractAddress, amount, parameters); this.node2.WaitMempoolCount(1); this.node2.WaitForBlocksToBeMined(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Storage set correctly Assert.Equal(BitConverter.GetBytes(NestedCallsStarter.Return), this.node1.GetStorageValue(preResponse.NewContractAddress, NestedCallsStarter.Key)); // Received 1/2 the sent funds + 1/2 of those funds Money transferAmount1 = new Money((long)amount, MoneyUnit.BTC) / 2; Money transferAmount2 = new Money((long)amount, MoneyUnit.BTC) / 4; Assert.Equal((ulong)(transferAmount1 + transferAmount2), this.node1.GetContractBalance(preResponse.NewContractAddress)); // Received 1/2 the sent funds, but sent 1/2 of those funds back Assert.Equal((ulong)(new Money((long)amount, MoneyUnit.BTC) - (transferAmount1 + transferAmount2)), this.node1.GetContractBalance(receiveResponse.NewContractAddress)); }
public void InternalTransfer_Create_WithValueTransfer() { // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/CreationTransfer.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.node1.WaitMempoolCount(1); this.node1.WaitForBlocksToBeMined(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); double amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send amount to contract, which will send to new address of contract it creates BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(CreationTransfer.CreateAnotherContract), preResponse.NewContractAddress, amount); this.node2.WaitMempoolCount(1); this.node2.WaitForBlocksToBeMined(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Get created contract address - TODO FIX uint160 createdAddress = this.addressGenerator.GenerateAddress(response.TransactionId, 0); // Contract doesn't maintain any balance Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress)); // Created contract received full amount Assert.Equal((ulong)new Money((ulong)amount, MoneyUnit.BTC), this.node1.GetContractBalance(createdAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network))); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public Block(NBitcoin.Block block) { this.Id = Block.ToId(block.GetHash()); this.Dificulty = block.Header.Bits.Difficulty; this.MerkleRoot = block.Header.HashMerkleRoot.ToString(); this.Version = block.Header.Version; this.Nonce = block.Header.Nonce; this.PreviousBlock = Block.ToId(block.Header.HashPrevBlock); this.HumanTime = block.Header.BlockTime; this.Time = this.HumanTime.UtcTicks; this.UnixTime = HumanTime.ToUnixTimeSeconds(); this.TransactionList = block.Transactions.Select(x => Transaction.ToId(x.GetHash())).ToList(); this.Transactions = block.Transactions.Count; }
public void InternalTransfer_FromConstructor() { double amount = 25; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/TransferFromConstructor.cs"); Assert.True(compilationResult.Success); uint160 walletUint160 = new uint160(1); string address = walletUint160.ToBase58Address(this.node1.CoreNode.FullNode.Network); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, address) }; BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount, parameters); this.node2.WaitMempoolCount(1); this.node2.WaitForBlocksToBeMined(1); Assert.NotNull(this.node1.GetCode(response.NewContractAddress)); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract maintains half the balance Assert.Equal((ulong)new Money((long)amount, MoneyUnit.BTC) / 2, this.node1.GetContractBalance(response.NewContractAddress)); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Equal(response.NewContractAddress, receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Null(receipt.To); }
public void PersistentState_Clear_State_Should_Be_Empty_In_Same_Tx() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/ClearDataContract.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Clear the data and check that it's empty BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(ClearDataContract.ClearDataAndCheck), preResponse.NewContractAddress, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.True(receipt.Success); Assert.Equal(true.ToString(), receipt.ReturnValue); }
public Transaction(NBitcoin.Block parent, NBitcoin.Transaction tx) { this.Id = Transaction.ToId(tx.GetHash()); this.BlockId = Block.ToId(parent.GetHash()); this.Size = tx.GetVirtualSize(); this.Version = tx.Version; this.LockType = tx.GetLockType(); this.LockTime = tx.LockTime.Value; this.IsCoinBase = tx.IsCoinBase; this.HasWitness = tx.HasWitness; this.InputCount = tx.Inputs.Count; this.InputTransactions = new InTransaction[InputCount]; this.OutputCount = tx.Outputs.Count; this.OutputTransactions = new OutTransaction[OutputCount]; this.OutputBtc = tx.TotalOut.ToDecimal(MoneyUnit.BTC); for (int i = 0; i < InputCount; i++) { var inTx = tx.Inputs[i]; // Is this a Coinbase? string payer = null; if (inTx.PrevOut.IsNull) { // Yes. payer = inTx.PrevOut.Hash.ToString(); } InputTransactions[i] = new InTransaction { Index = (uint)i, Outpoint = new Outpoint { Index = inTx.PrevOut.N, TxId = Transaction.ToId(inTx.PrevOut.Hash.ToString()) }, Payer = payer, PayerType = AddressType.None, Value = 0 }; } for (int i = 0; i < OutputCount; i++) { var outTx = tx.Outputs[i]; AddressType type = outTx.GetAddressType(); string payee; if (type == AddressType.PublicKey) { payee = outTx.ScriptPubKey.GetDestinationPublicKeys().FirstOrDefault()?.ToString(); } else if (type == AddressType.ScriptHash) { payee = outTx.ScriptPubKey.GetScriptAddress(Network.Main).Hash.ToString(); } else if (type == AddressType.MultiplePublicKeyHashes) { payee = outTx.ScriptPubKey.GetDestinationPublicKeys()[0].GetAddress(Network.Main).ToString(); } else { payee = outTx.ScriptPubKey?.GetDestinationAddress(Network.Main)?.ToString(); } OutputTransactions[i] = new OutTransaction { Index = (uint)i, Payee = payee, PayeeType = type, Value = outTx.Value.ToDecimal(MoneyUnit.BTC) }; } }
public void CreateContract_OneOfEachParameterType() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); decimal amount = 25; uint256 currentHash = this.node1.GetLastBlock().GetHash(); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/CreateWithAllParameters.cs"); Assert.True(compilationResult.Success); const char testChar = 'c'; string testAddressBase58 = new uint160("0x0000000000000000000000000000000000000001").ToBase58Address(this.node1.CoreNode.FullNode.Network); Address testAddress = testAddressBase58.ToAddress(this.node1.CoreNode.FullNode.Network); const bool testBool = true; const int testInt = Int32.MaxValue; const long testLong = Int64.MaxValue; const uint testUint = UInt32.MaxValue; const ulong testUlong = UInt64.MaxValue; const string testString = "The quick brown fox jumps over the lazy dog"; byte[] testBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Char, testChar), string.Format("{0}#{1}", (int)MethodParameterDataType.Address, testAddressBase58), string.Format("{0}#{1}", (int)MethodParameterDataType.Bool, testBool), string.Format("{0}#{1}", (int)MethodParameterDataType.Int, testInt), string.Format("{0}#{1}", (int)MethodParameterDataType.Long, testLong), string.Format("{0}#{1}", (int)MethodParameterDataType.UInt, testUint), string.Format("{0}#{1}", (int)MethodParameterDataType.ULong, testUlong), string.Format("{0}#{1}", (int)MethodParameterDataType.String, testString), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, testBytes.ToHexString()), }; BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract was created Assert.NotNull(this.node1.GetCode(response.NewContractAddress)); // Block doesn't contain any extra transactions Assert.Equal(2, lastBlock.Transactions.Count); // Contract keeps balance Assert.Equal((ulong)new Money((ulong)amount, MoneyUnit.BTC), this.node1.GetContractBalance(response.NewContractAddress)); // All values were stored Assert.Equal(this.serializer.Serialize(testChar), this.node1.GetStorageValue(response.NewContractAddress, "char")); Assert.Equal(this.serializer.Serialize(testAddress), this.node1.GetStorageValue(response.NewContractAddress, "Address")); Assert.Equal(this.serializer.Serialize(testBool), this.node1.GetStorageValue(response.NewContractAddress, "bool")); Assert.Equal(this.serializer.Serialize(testInt), this.node1.GetStorageValue(response.NewContractAddress, "int")); Assert.Equal(this.serializer.Serialize(testLong), this.node1.GetStorageValue(response.NewContractAddress, "long")); Assert.Equal(this.serializer.Serialize(testUint), this.node1.GetStorageValue(response.NewContractAddress, "uint")); Assert.Equal(this.serializer.Serialize(testUlong), this.node1.GetStorageValue(response.NewContractAddress, "ulong")); Assert.Equal(this.serializer.Serialize(testString), this.node1.GetStorageValue(response.NewContractAddress, "string")); Assert.Equal(testBytes, this.node1.GetStorageValue(response.NewContractAddress, "bytes")); // Test that the contract address, event name, and logging values are available in the bloom. var scBlockHeader = lastBlock.Header as ISmartContractBlockHeader; Assert.True(scBlockHeader.LogsBloom.Test(response.NewContractAddress.ToUint160(this.node1.CoreNode.FullNode.Network).ToBytes())); Assert.True(scBlockHeader.LogsBloom.Test(Encoding.UTF8.GetBytes("Log"))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testChar))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testAddress))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testBool))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testInt))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testLong))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testUint))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testUlong))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testString))); Assert.True(scBlockHeader.LogsBloom.Test(this.serializer.Serialize(testBytes))); // And sanity test that random fields aren't contained in bloom. Assert.False(scBlockHeader.LogsBloom.Test(Encoding.UTF8.GetBytes("RandomValue"))); Assert.False(scBlockHeader.LogsBloom.Test(BitConverter.GetBytes(123))); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.True(receipt.Success); Assert.Single(receipt.Logs); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Equal(response.NewContractAddress, receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.To); Assert.Null(receipt.Error); }
public void SerializeArrays_ForEachMethodParamType() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); decimal amount = 25; uint256 currentHash = this.node1.GetLastBlock().GetHash(); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/CreateWithAllArrays.cs"); Assert.True(compilationResult.Success); char[] chars = new char[] { 'a', '9' }; Address[] addresses = new Address[] { this.node1.MinerAddress.Address.ToAddress(this.node1.CoreNode.FullNode.Network), "mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn".ToAddress(this.node1.CoreNode.FullNode.Network) }; bool[] bools = new bool[] { false, true, false }; int[] ints = new int[] { 1, -123, int.MaxValue }; long[] longs = new long[] { 1, -123, long.MaxValue }; uint[] uints = new uint[] { 1, 123, uint.MaxValue }; ulong[] ulongs = new ulong[] { 1, 123, ulong.MaxValue }; string[] strings = new string[] { "Test", "", "The quick brown fox jumps over the lazy dog" }; // TODO: Ensure Assert checks "" equality in contract when null bug fixed string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(chars).ToHexString()), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(addresses).ToHexString()), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(bools).ToHexString()), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(ints).ToHexString()), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(longs).ToHexString()), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(uints).ToHexString()), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(ulongs).ToHexString()), string.Format("{0}#{1}", (int)MethodParameterDataType.ByteArray, this.serializer.Serialize(strings).ToHexString()) }; BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract was created Assert.NotNull(this.node1.GetCode(response.NewContractAddress)); // Block doesn't contain any extra transactions Assert.Equal(2, lastBlock.Transactions.Count); // Contract keeps balance Assert.Equal((ulong)new Money((ulong)amount, MoneyUnit.BTC), this.node1.GetContractBalance(response.NewContractAddress)); // All values were stored Assert.Equal(this.serializer.Serialize(chars), this.node1.GetStorageValue(response.NewContractAddress, "chars")); Assert.Equal(this.serializer.Serialize(addresses), this.node1.GetStorageValue(response.NewContractAddress, "addresses")); Assert.Equal(this.serializer.Serialize(bools), this.node1.GetStorageValue(response.NewContractAddress, "bools")); Assert.Equal(this.serializer.Serialize(ints), this.node1.GetStorageValue(response.NewContractAddress, "ints")); Assert.Equal(this.serializer.Serialize(longs), this.node1.GetStorageValue(response.NewContractAddress, "longs")); Assert.Equal(this.serializer.Serialize(uints), this.node1.GetStorageValue(response.NewContractAddress, "uints")); Assert.Equal(this.serializer.Serialize(ulongs), this.node1.GetStorageValue(response.NewContractAddress, "ulongs")); Assert.Equal(this.serializer.Serialize(strings), this.node1.GetStorageValue(response.NewContractAddress, "strings")); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.True(receipt.Success); Assert.Empty(receipt.Logs); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Equal(response.NewContractAddress, receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.To); Assert.Null(receipt.Error); }
public void Internal_CallContract_SerializeEachParameterType() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract to send to ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/CallWithAllParameters.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; uint256 currentHash = this.node1.GetLastBlock().GetHash(); const char testChar = 'c'; string testAddressBase58 = new uint160("0x0000000000000000000000000000000000000001").ToBase58Address(this.node1.CoreNode.FullNode.Network); const bool testBool = true; const int testInt = Int32.MaxValue; const long testLong = Int64.MaxValue; const uint testUint = UInt32.MaxValue; const ulong testUlong = UInt64.MaxValue; const string testString = "The quick brown fox jumps over the lazy dog"; string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Char, testChar), string.Format("{0}#{1}", (int)MethodParameterDataType.Address, testAddressBase58), string.Format("{0}#{1}", (int)MethodParameterDataType.Bool, testBool), string.Format("{0}#{1}", (int)MethodParameterDataType.Int, testInt), string.Format("{0}#{1}", (int)MethodParameterDataType.Long, testLong), string.Format("{0}#{1}", (int)MethodParameterDataType.UInt, testUint), string.Format("{0}#{1}", (int)MethodParameterDataType.ULong, testUlong), string.Format("{0}#{1}", (int)MethodParameterDataType.String, testString), string.Format("{0}#{1}", (int)MethodParameterDataType.Address, preResponse.NewContractAddress) // sendTo }; compilationResult = ContractCompiler.CompileFile("SmartContracts/ForwardParameters.cs"); BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains extra transaction forwarding balance Assert.Equal(3, lastBlock.Transactions.Count); // Contract called internally gets balance Assert.Equal((ulong)new Money((ulong)amount, MoneyUnit.BTC), this.node1.GetContractBalance(preResponse.NewContractAddress)); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.True(receipt.Success); Assert.Empty(receipt.Logs); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Equal(response.NewContractAddress, receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.To); Assert.Null(receipt.Error); }
public void InternalTransfer_BetweenContracts() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract to send to ContractCompilationResult receiveCompilationResult = ContractCompiler.CompileFile("SmartContracts/NestedCallsReceiver.cs"); Assert.True(receiveCompilationResult.Success); BuildCreateContractTransactionResponse receiveResponse = this.node1.SendCreateContractTransaction(receiveCompilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(receiveResponse.NewContractAddress)); // Deploy contract to send from ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/NestedCallsStarter.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, receiveResponse.NewContractAddress) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction(nameof(NestedCallsStarter.Start), preResponse.NewContractAddress, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Storage set correctly Assert.Equal(BitConverter.GetBytes(NestedCallsStarter.Return), this.node1.GetStorageValue(preResponse.NewContractAddress, NestedCallsStarter.Key)); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Equal(2, condensingTransaction.Outputs.Count); // 1 output which is starting contract byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(preResponse.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); // Received 1/2 the sent funds + 1/2 of those funds Money transferAmount1 = new Money((long)amount, MoneyUnit.BTC) / 2; Money transferAmount2 = new Money((long)amount, MoneyUnit.BTC) / 4; Assert.Equal(transferAmount1 + transferAmount2, condensingTransaction.Outputs[0].Value); Assert.Equal((ulong)(transferAmount1 + transferAmount2), this.node1.GetContractBalance(preResponse.NewContractAddress)); // 1 output to other deployed contract toBytes = condensingTransaction.Outputs[1].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(receiveResponse.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); // Received 1/2 the sent funds, but sent 1/2 of those funds back Assert.Equal(new Money((long)amount, MoneyUnit.BTC) - (transferAmount1 + transferAmount2), condensingTransaction.Outputs[1].Value); Assert.Equal((ulong)(new Money((long)amount, MoneyUnit.BTC) - (transferAmount1 + transferAmount2)), this.node1.GetContractBalance(receiveResponse.NewContractAddress)); }
public SmartContractsPoARegTest() { this.Name = "SmartContractsPoARegTest"; this.NetworkType = NetworkType.Regtest; this.CoinTicker = "SCPOA"; var consensusFactory = new SmartContractPoAConsensusFactory(); // Create the genesis block. this.GenesisTime = 1513622125; this.GenesisNonce = 1560058197; this.GenesisBits = 402691653; this.GenesisVersion = 1; this.GenesisReward = Money.Zero; NBitcoin.Block genesisBlock = CreatePoAGenesisBlock(consensusFactory, this.GenesisTime, this.GenesisNonce, this.GenesisBits, this.GenesisVersion, this.GenesisReward); ((SmartContractPoABlockHeader)genesisBlock.Header).HashStateRoot = new uint256("21B463E3B52F6201C0AD6C991BE0485B6EF8C092E64583FFA655CC1B171FE856"); // Set StateRoot to empty trie. this.Genesis = genesisBlock; // Keeping the 3rd there in case we use it in future. For our integration tests we use 2 nodes currently. this.FederationKeys = new Key[] { new Mnemonic("lava frown leave wedding virtual ghost sibling able mammal liar wide wisdom").DeriveExtKey().PrivateKey, new Mnemonic("idle power swim wash diesel blouse photo among eager reward govern menu").DeriveExtKey().PrivateKey, new Mnemonic("high neither night category fly wasp inner kitchen phone current skate hair").DeriveExtKey().PrivateKey }; var genesisFederationMembers = new List <IFederationMember> { new FederationMember(this.FederationKeys[0].PubKey), // 029528e83f065153d7fa655e73a07fc96fc759162f1e2c8936fa592f2942f39af0 new FederationMember(this.FederationKeys[1].PubKey), // 03b539807c64abafb2d14c52a0d1858cc29d7c7fad0598f92a1274789c18d74d2d new FederationMember(this.FederationKeys[2].PubKey) // 02d6792cf941b68edd1e9056653573917cbaf974d46e9eeb9801d6fcedf846477a }; var consensusOptions = new PoAConsensusOptions( maxBlockBaseSize: 500_000, // Half the standard block size / weight. Easier to stress test. maxStandardVersion: 2, maxStandardTxWeight: 100_000, maxBlockSigopsCost: 20_000, maxStandardTxSigopsCost: 20_000 / 5, genesisFederationMembers: genesisFederationMembers, targetSpacingSeconds: 60, votingEnabled: true, autoKickIdleMembers: false ); var buriedDeployments = new BuriedDeploymentsArray { [BuriedDeployments.BIP34] = 0, [BuriedDeployments.BIP65] = 0, [BuriedDeployments.BIP66] = 0 }; var bip9Deployments = new NoBIP9Deployments(); this.Consensus = new Consensus( consensusFactory: consensusFactory, consensusOptions: consensusOptions, coinType: 105, hashGenesisBlock: genesisBlock.GetHash(), subsidyHalvingInterval: 210000, majorityEnforceBlockUpgrade: 750, majorityRejectBlockOutdated: 950, majorityWindow: 1000, buriedDeployments: buriedDeployments, bip9Deployments: bip9Deployments, bip34Hash: new uint256("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"), ruleChangeActivationThreshold: 1916, // 95% of 2016 minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing maxReorgLength: 500, defaultAssumeValid: null, maxMoney: long.MaxValue, coinbaseMaturity: 1, premineHeight: 5, premineReward: Money.Coins(100_000_000), proofOfWorkReward: Money.Coins(0), powTargetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks powTargetSpacing: TimeSpan.FromSeconds(60), powAllowMinDifficultyBlocks: false, posNoRetargeting: true, powNoRetargeting: true, powLimit: null, minimumChainWork: null, isProofOfStake: false, lastPowBlock: 0, proofOfStakeLimit: null, proofOfStakeLimitV2: null, proofOfStakeReward: Money.Zero ); // Same as current smart contracts test networks to keep tests working this.Base58Prefixes = new byte[12][]; this.Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (111) }; this.Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (196) }; this.Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (239) }; this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_NO_EC] = new byte[] { 0x01, 0x42 }; this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_EC] = new byte[] { 0x01, 0x43 }; this.Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x35), (0x87), (0xCF) }; this.Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x35), (0x83), (0x94) }; this.Base58Prefixes[(int)Base58Type.PASSPHRASE_CODE] = new byte[] { 0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2 }; this.Base58Prefixes[(int)Base58Type.CONFIRMATION_CODE] = new byte[] { 0x64, 0x3B, 0xF6, 0xA8, 0x9A }; this.Base58Prefixes[(int)Base58Type.STEALTH_ADDRESS] = new byte[] { 0x2b }; this.Base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 115 }; this.Base58Prefixes[(int)Base58Type.COLORED_ADDRESS] = new byte[] { 0x13 }; Bech32Encoder encoder = Encoders.Bech32("tb"); this.Bech32Encoders = new Bech32Encoder[2]; this.Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder; this.Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder; this.Checkpoints = new Dictionary <int, CheckpointInfo>(); this.DNSSeeds = new List <DNSSeedData>(); this.SeedNodes = new List <NetworkAddress>(); this.StandardScriptsRegistry = new SmartContractsStandardScriptsRegistry(); // TODO: Do we need Asserts for block hash this.RegisterRules(this.Consensus); this.RegisterMempoolRules(this.Consensus); }
public void InternalTransfer_Create_WithValueTransfer() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/CreationTransfer.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send amount to contract, which will send to new address of contract it creates BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(CreationTransfer.CreateAnotherContract), preResponse.NewContractAddress, amount); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Get created contract address - TODO FIX uint160 createdAddress = this.addressGenerator.GenerateAddress(response.TransactionId, 0); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Single(condensingTransaction.Outputs); // Entire balance was forwarded, byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(createdAddress, toAddress); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), condensingTransaction.Outputs[0].Value); // Contract doesn't maintain any balance Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress)); // Created contract received full amount Assert.Equal((ulong)new Money((ulong)amount, MoneyUnit.BTC), this.node1.GetContractBalance(createdAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network))); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
private void ReceiveBlock(Block block, BlockType blockType = BlockType.Main) { var hash = block.GetHash(); foreach(var tx in block.Transactions) { ReceiveTransaction(hash, blockType, tx); } }
public void Persisting_Nothing_Null_And_Empty_Byte_Arrays_Are_The_Same() { // Demonstrates some potentially unusual behaviour when saving contract state. // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/BehaviourTest.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Call CheckData() and confirm that it succeeds BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(BehaviourTest.DataIsByte0), preResponse.NewContractAddress, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.True(receipt.Success); // Invoke PersistEmptyString. It should succeed response = this.node1.SendCallContractTransaction( nameof(BehaviourTest.PersistEmptyString), preResponse.NewContractAddress, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.True(receipt.Success); // The storage value should be null, but the contract only sees it as a byte[0] Assert.Null(this.node1.GetStorageValue(preResponse.NewContractAddress, nameof(BehaviourTest.Data))); // Now call CheckData() to confirm that it's a byte[0] response = this.node1.SendCallContractTransaction( nameof(BehaviourTest.DataIsByte0), preResponse.NewContractAddress, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.True(receipt.Success); // Now call PersistNull, which should fail if the null is not returned as byte[0] response = this.node1.SendCallContractTransaction( nameof(BehaviourTest.PersistNull), preResponse.NewContractAddress, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); lastBlock = this.node1.GetLastBlock(); receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.True(receipt.Success); // The storage value should be null Assert.Null(this.node1.GetStorageValue(preResponse.NewContractAddress, nameof(BehaviourTest.Data))); // Now call CheckData() to confirm that it's a byte[0] response = this.node1.SendCallContractTransaction( nameof(BehaviourTest.DataIsByte0), preResponse.NewContractAddress, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.True(receipt.Success); }
public Task PutAsync(Block block) { return PutAsync(block.GetHash(), block); }
public Task PutAsync(Block block) { return(PutAsync(block.GetHash(), block)); }
public SmartContractsPoATest() { this.CoinName = "Stratis"; this.NetworkName = "SmartContractsPoATest"; this.CoinTicker = "SCPOA"; var consensusFactory = new SmartContractPoAConsensusFactory(); var messageStart = new byte[4]; messageStart[0] = 0x76; messageStart[1] = 0x36; messageStart[2] = 0x23; messageStart[3] = 0x07; // Incremented 6/12/18 uint magic = BitConverter.ToUInt32(messageStart, 0); this.Magic = magic; // Create the genesis block. this.GenesisTime = 1513622125; // TODO: Very important! Increase for future SC test networks to roughly the time we start. this.GenesisNonce = 1560058198; // Incremented 6/12/18 this.GenesisBits = 402691653; this.GenesisVersion = 1; this.GenesisReward = Money.Zero; NBitcoin.Block genesisBlock = CreatePoAGenesisBlock(consensusFactory, this.GenesisTime, this.GenesisNonce, this.GenesisBits, this.GenesisVersion, this.GenesisReward); ((SmartContractPoABlockHeader)genesisBlock.Header).HashStateRoot = new uint256("21B463E3B52F6201C0AD6C991BE0485B6EF8C092E64583FFA655CC1B171FE856"); // Set StateRoot to empty trie. this.Genesis = genesisBlock; var federationPubKeys = new List <PubKey> { new PubKey("03df4a360038a42b68aca8d198fc487c495ef9e4f3fe56daa6bbfdeea1a7cb5ec5"), new PubKey("021c3e5b81a43284d166fb8862a9e7382630c2750f8556a4c7ba405ccdd70d4808"), new PubKey("03a5055a77126a21b6d899482332bd9b2cc88fb96e83b172769754dee852a74316"), new PubKey("03c9e8888a2d32b1022349a3bbf1aa325ed908f066bb0ebba8a1fe5eb6cabf3b7a"), new PubKey("0282d9d0dcb978ecf1411c5cad744059ff75bdc9b352ab9454cf92ffe8cdf14789"), new PubKey("02998a6d9a13446678e9f892c1fcc61834d1d439dd97d57fc9e30b51020d2277e4"), new PubKey("037ab82c35af49860021e89c6868cd4a4b6f839cd1a3094dc828908ce9d86cf94a") }; var consensusOptions = new PoAConsensusOptions( maxBlockBaseSize: 1_000_000, maxStandardVersion: 2, maxStandardTxWeight: 100_000, maxBlockSigopsCost: 20_000, maxStandardTxSigopsCost: 20_000 / 5, federationPublicKeys: federationPubKeys, targetSpacingSeconds: 60, votingEnabled: true ); var buriedDeployments = new BuriedDeploymentsArray { [BuriedDeployments.BIP34] = 0, [BuriedDeployments.BIP65] = 0, [BuriedDeployments.BIP66] = 0 }; var bip9Deployments = new NoBIP9Deployments(); this.Consensus = new Consensus( consensusFactory: consensusFactory, consensusOptions: consensusOptions, coinType: 105, hashGenesisBlock: genesisBlock.GetHash(), subsidyHalvingInterval: 210000, majorityEnforceBlockUpgrade: 750, majorityRejectBlockOutdated: 950, majorityWindow: 1000, buriedDeployments: buriedDeployments, bip9Deployments: bip9Deployments, bip34Hash: new uint256("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"), ruleChangeActivationThreshold: 1916, // 95% of 2016 minerConfirmationWindow: 2016, // nPowTargetTimespan / nPowTargetSpacing maxReorgLength: 500, defaultAssumeValid: null, maxMoney: long.MaxValue, coinbaseMaturity: 1, premineHeight: 5, premineReward: Money.Coins(100_000_000), proofOfWorkReward: Money.Coins(0), powTargetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks powTargetSpacing: TimeSpan.FromSeconds(60), powAllowMinDifficultyBlocks: false, posNoRetargeting: true, powNoRetargeting: true, powLimit: null, minimumChainWork: null, isProofOfStake: false, lastPowBlock: 0, proofOfStakeLimit: null, proofOfStakeLimitV2: null, proofOfStakeReward: Money.Zero ); // Same as current smart contracts test networks to keep tests working this.Base58Prefixes = new byte[12][]; this.Base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (111) }; this.Base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (196) }; this.Base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (239) }; this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_NO_EC] = new byte[] { 0x01, 0x42 }; this.Base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_EC] = new byte[] { 0x01, 0x43 }; this.Base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x35), (0x87), (0xCF) }; this.Base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x35), (0x83), (0x94) }; this.Base58Prefixes[(int)Base58Type.PASSPHRASE_CODE] = new byte[] { 0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2 }; this.Base58Prefixes[(int)Base58Type.CONFIRMATION_CODE] = new byte[] { 0x64, 0x3B, 0xF6, 0xA8, 0x9A }; this.Base58Prefixes[(int)Base58Type.STEALTH_ADDRESS] = new byte[] { 0x2b }; this.Base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 115 }; this.Base58Prefixes[(int)Base58Type.COLORED_ADDRESS] = new byte[] { 0x13 }; Bech32Encoder encoder = Encoders.Bech32("tb"); this.Bech32Encoders = new Bech32Encoder[2]; this.Bech32Encoders[(int)Bech32Type.WITNESS_PUBKEY_ADDRESS] = encoder; this.Bech32Encoders[(int)Bech32Type.WITNESS_SCRIPT_ADDRESS] = encoder; this.Checkpoints = new Dictionary <int, CheckpointInfo>(); this.DNSSeeds = new List <DNSSeedData>(); this.SeedNodes = new List <NetworkAddress>(); this.StandardScriptsRegistry = new SmartContractsStandardScriptsRegistry(); // TODO: Do we need Asserts for block hash }
private void InitMain() { SpendableCoinbaseDepth = 100; name = "Main"; consensus.SubsidyHalvingInterval = 210000; consensus.MajorityEnforceBlockUpgrade = 750; consensus.MajorityRejectBlockOutdated = 950; consensus.MajorityWindow = 1000; consensus.BIP34Height = 227931; consensus.BIP34Hash = new uint256("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"); consensus.PowLimit = new Target(new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); consensus.SegWitHeight = 2000000000; consensus.PowTargetTimespan = TimeSpan.FromSeconds(14 * 24 * 60 * 60); // two weeks consensus.PowTargetSpacing = TimeSpan.FromSeconds(10 * 60); consensus.PowAllowMinDifficultyBlocks = false; consensus.PowNoRetargeting = false; // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. magic = 0xD9B4BEF9; vAlertPubKey = Encoders.Hex.DecodeData("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"); nDefaultPort = 8333; nRPCPort = 8332; nSubsidyHalvingInterval = 210000; genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, Money.Coins(50m)); consensus.HashGenesisBlock = genesis.GetHash(); assert(consensus.HashGenesisBlock == uint256.Parse("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")); assert(genesis.Header.HashMerkleRoot == uint256.Parse("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); #if !NOSOCKET vSeeds.Add(new DNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be")); // Pieter Wuille vSeeds.Add(new DNSSeedData("bluematt.me", "dnsseed.bluematt.me")); // Matt Corallo vSeeds.Add(new DNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr vSeeds.Add(new DNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker vSeeds.Add(new DNSSeedData("xf2.org", "bitseed.xf2.org")); // Jeff Garzik vSeeds.Add(new DNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch")); // Jonas Schnelli #endif base58Prefixes[(int)Base58Type.PUBKEY_ADDRESS] = new byte[] { (0) }; base58Prefixes[(int)Base58Type.SCRIPT_ADDRESS] = new byte[] { (5) }; base58Prefixes[(int)Base58Type.SECRET_KEY] = new byte[] { (128) }; base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_NO_EC] = new byte[] { 0x01, 0x42 }; base58Prefixes[(int)Base58Type.ENCRYPTED_SECRET_KEY_EC] = new byte[] { 0x01, 0x43 }; base58Prefixes[(int)Base58Type.EXT_PUBLIC_KEY] = new byte[] { (0x04), (0x88), (0xB2), (0x1E) }; base58Prefixes[(int)Base58Type.EXT_SECRET_KEY] = new byte[] { (0x04), (0x88), (0xAD), (0xE4) }; base58Prefixes[(int)Base58Type.PASSPHRASE_CODE] = new byte[] { 0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2 }; base58Prefixes[(int)Base58Type.CONFIRMATION_CODE] = new byte[] { 0x64, 0x3B, 0xF6, 0xA8, 0x9A }; base58Prefixes[(int)Base58Type.STEALTH_ADDRESS] = new byte[] { 0x2a }; base58Prefixes[(int)Base58Type.ASSET_ID] = new byte[] { 23 }; base58Prefixes[(int)Base58Type.COLORED_ADDRESS] = new byte[] { 0x13 }; base58Prefixes[(int)Base58Type.WITNESS_P2WPKH] = new byte[] { 0x6 }; base58Prefixes[(int)Base58Type.WITNESS_P2WSH] = new byte[] { (10) }; #if !NOSOCKET // Convert the pnSeeds array into usable address objects. Random rand = new Random(); TimeSpan nOneWeek = TimeSpan.FromDays(7); for (int i = 0; i < pnSeed.Length; i++) { // It'll only connect to one or two seed nodes because once it connects, // it'll get a pile of addresses with newer timestamps. NetworkAddress addr = new NetworkAddress(); // Seed nodes are given a random 'last seen time' of between one and two // weeks ago. addr.Time = DateTime.UtcNow - (TimeSpan.FromSeconds(rand.NextDouble() * nOneWeek.TotalSeconds)) - nOneWeek; addr.Endpoint = Utils.ParseIpEndpoint(pnSeed[i], DefaultPort); vFixedSeeds.Add(addr); } #endif }
public void InternalTransfer_FromConstructor() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/TransferFromConstructor.cs"); Assert.True(compilationResult.Success); uint160 walletUint160 = new uint160(1); string address = walletUint160.ToBase58Address(this.node1.CoreNode.FullNode.Network); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, address) }; BuildCreateContractTransactionResponse response = this.node1.SendCreateContractTransaction(compilationResult.Compilation, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(response.NewContractAddress)); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Equal(2, condensingTransaction.Outputs.Count); // 1 output which is contract maintaining its balance byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(response.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC) / 2, condensingTransaction.Outputs[1].Value); // 1 output to address sent in params uint160 transferReceiver = this.senderRetriever.GetAddressFromScript(condensingTransaction.Outputs[1].ScriptPubKey).Sender; Assert.Equal(walletUint160, transferReceiver); Assert.Equal(new Money((long)amount, MoneyUnit.BTC) / 2, condensingTransaction.Outputs[1].Value); // Contract maintains half the balance Assert.Equal((ulong)new Money((long)amount, MoneyUnit.BTC) / 2, this.node1.GetContractBalance(response.NewContractAddress)); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Equal(response.NewContractAddress, receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Null(receipt.To); }
private static Network InitStratisMain() { Block.BlockSignature = true; Transaction.TimeStamp = true; var consensus = new Consensus(); consensus.NetworkOptions = new NetworkOptions() { IsProofOfStake = true }; consensus.GetPoWHash = (n, h) => Crypto.HashX13.Instance.Hash(h.ToBytes(options:n)); consensus.SubsidyHalvingInterval = 210000; consensus.MajorityEnforceBlockUpgrade = 750; consensus.MajorityRejectBlockOutdated = 950; consensus.MajorityWindow = 1000; consensus.BuriedDeployments[BuriedDeployments.BIP34] = 227931; consensus.BuriedDeployments[BuriedDeployments.BIP65] = 388381; consensus.BuriedDeployments[BuriedDeployments.BIP66] = 363725; consensus.BIP34Hash = new uint256("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8"); consensus.PowLimit = new Target(new uint256("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); consensus.PowTargetTimespan = TimeSpan.FromSeconds(14 * 24 * 60 * 60); // two weeks consensus.PowTargetSpacing = TimeSpan.FromSeconds(10 * 60); consensus.PowAllowMinDifficultyBlocks = false; consensus.PowNoRetargeting = false; consensus.RuleChangeActivationThreshold = 1916; // 95% of 2016 consensus.MinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing consensus.BIP9Deployments[BIP9Deployments.TestDummy] = new BIP9DeploymentsParameters(28, 1199145601, 1230767999); consensus.BIP9Deployments[BIP9Deployments.CSV] = new BIP9DeploymentsParameters(0, 1462060800, 1493596800); consensus.BIP9Deployments[BIP9Deployments.Segwit] = new BIP9DeploymentsParameters(1, 0, 0); consensus.LastPOWBlock = 12500; consensus.ProofOfStakeLimit = new BigInteger(uint256.Parse("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)); consensus.ProofOfStakeLimitV2 = new BigInteger(uint256.Parse("000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff").ToBytes(false)); consensus.CoinType = 105; consensus.DefaultAssumeValid = new uint256("0x8c2cf95f9ca72e13c8c4cdf15c2d7cc49993946fb49be4be147e106d502f1869"); // 642930 Block genesis = CreateStratisGenesisBlock(1470467000, 1831645, 0x1e0fffff, 1, Money.Zero); consensus.HashGenesisBlock = genesis.GetHash(consensus.NetworkOptions); // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. var messageStart = new byte[4]; messageStart[0] = 0x70; messageStart[1] = 0x35; messageStart[2] = 0x22; messageStart[3] = 0x05; var magic = BitConverter.ToUInt32(messageStart, 0); //0x5223570; Assert(consensus.HashGenesisBlock == uint256.Parse("0x0000066e91e46e5a264d42c89e1204963b2ee6be230b443e9159020539d972af")); Assert(genesis.Header.HashMerkleRoot == uint256.Parse("0x65a26bc20b0351aebf05829daefa8f7db2f800623439f3c114257c91447f1518")); var builder = new NetworkBuilder() .SetName("StratisMain") .SetConsensus(consensus) .SetMagic(magic) .SetGenesis(genesis) .SetPort(16178) .SetRPCPort(16174) .SetTxFees(10000, 60000, 10000) .AddDNSSeeds(new[] { new DNSSeedData("seednode1.stratisplatform.com", "seednode1.stratisplatform.com"), new DNSSeedData("seednode2.stratis.cloud", "seednode2.stratis.cloud"), new DNSSeedData("seednode3.stratisplatform.com", "seednode3.stratisplatform.com"), new DNSSeedData("seednode4.stratis.cloud", "seednode4.stratis.cloud") }) .SetBase58Bytes(Base58Type.PUBKEY_ADDRESS, new byte[] {(63)}) .SetBase58Bytes(Base58Type.SCRIPT_ADDRESS, new byte[] {(125)}) .SetBase58Bytes(Base58Type.SECRET_KEY, new byte[] {(63 + 128)}) .SetBase58Bytes(Base58Type.ENCRYPTED_SECRET_KEY_NO_EC, new byte[] {0x01, 0x42}) .SetBase58Bytes(Base58Type.ENCRYPTED_SECRET_KEY_EC, new byte[] {0x01, 0x43}) .SetBase58Bytes(Base58Type.EXT_PUBLIC_KEY, new byte[] {(0x04), (0x88), (0xB2), (0x1E)}) .SetBase58Bytes(Base58Type.EXT_SECRET_KEY, new byte[] {(0x04), (0x88), (0xAD), (0xE4)}) .SetBase58Bytes(Base58Type.PASSPHRASE_CODE, new byte[] {0x2C, 0xE9, 0xB3, 0xE1, 0xFF, 0x39, 0xE2}) .SetBase58Bytes(Base58Type.CONFIRMATION_CODE, new byte[] {0x64, 0x3B, 0xF6, 0xA8, 0x9A}) .SetBase58Bytes(Base58Type.STEALTH_ADDRESS, new byte[] {0x2a}) .SetBase58Bytes(Base58Type.ASSET_ID, new byte[] {23}) .SetBase58Bytes(Base58Type.COLORED_ADDRESS, new byte[] {0x13}) .SetBech32(Bech32Type.WITNESS_PUBKEY_ADDRESS, "bc") .SetBech32(Bech32Type.WITNESS_SCRIPT_ADDRESS, "bc"); var seed = new[] { "101.200.198.155", "103.24.76.21", "104.172.24.79" }; var fixedSeeds = new List<NetworkAddress>(); // Convert the pnSeeds array into usable address objects. Random rand = new Random(); TimeSpan oneWeek = TimeSpan.FromDays(7); for (int i = 0; i < seed.Length; i++) { // It'll only connect to one or two seed nodes because once it connects, // it'll get a pile of addresses with newer timestamps. NetworkAddress addr = new NetworkAddress(); // Seed nodes are given a random 'last seen time' of between one and two // weeks ago. addr.Time = DateTime.UtcNow - (TimeSpan.FromSeconds(rand.NextDouble() * oneWeek.TotalSeconds)) - oneWeek; addr.Endpoint = Utils.ParseIpEndpoint(seed[i], builder.Port); fixedSeeds.Add(addr); } builder.AddSeeds(fixedSeeds); return builder.BuildAndRegister(); }
public void InternalTransfer_ToWalletAddress() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/BasicTransfer.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send amount to contract, which will send to wallet address (address without code) uint160 walletUint160 = new uint160(1); string address = walletUint160.ToBase58Address(this.node1.CoreNode.FullNode.Network); string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, address) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(BasicTransfer.SendToAddress), preResponse.NewContractAddress, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Single(condensingTransaction.Outputs); // Entire balance was forwarded, uint160 transferReceiver = this.senderRetriever.GetAddressFromScript(condensingTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(walletUint160, transferReceiver); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), condensingTransaction.Outputs[0].Value); // Contract doesn't maintain any balance Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress)); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); // TODO: Could add logs to this test Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public void ContractTransaction_ExceptionInCall() { // Ensure fixture is funded. this.node1.MineBlocks(1); // Deploy contract ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/ExceptionInMethod.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.node1.WaitMempoolCount(1); this.node1.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); double amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction("Method", preResponse.NewContractAddress, amount); this.node2.WaitMempoolCount(1); this.node2.MineBlocks(1); Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // State wasn't persisted Assert.Null(this.node2.GetStorageValue(preResponse.NewContractAddress, "Test")); // Logs weren't persisted Assert.Equal(new Bloom(), ((SmartContractBlockHeader)lastBlock.Header).LogsBloom); // Block contains a refund transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction refundTransaction = lastBlock.Transactions[2]; Assert.Single(refundTransaction.Outputs); // No transfers persisted uint160 refundReceiver = this.senderRetriever.GetAddressFromScript(refundTransaction.Outputs[0].ScriptPubKey).Sender; Assert.Equal(this.node1.MinerAddress.Address, refundReceiver.ToAddress(this.mockChain.Network).Value); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), refundTransaction.Outputs[0].Value); Money fee = lastBlock.Transactions[0].Outputs[0].Value - new Money(50, MoneyUnit.BTC); // Amount was refunded to wallet, minus fee Assert.Equal(senderBalanceBefore - this.node1.WalletSpendableBalance, fee); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Empty(receipt.Logs); Assert.False(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.StartsWith("System.IndexOutOfRangeException", receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public void InternalTransfer_ToContractAddress() { // Ensure fixture is funded. this.mockChain.MineBlocks(1); // Deploy contract to send to ContractCompilationResult receiveCompilationResult = ContractCompiler.CompileFile("SmartContracts/BasicReceive.cs"); Assert.True(receiveCompilationResult.Success); BuildCreateContractTransactionResponse receiveResponse = this.node1.SendCreateContractTransaction(receiveCompilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(receiveResponse.NewContractAddress)); // Deploy contract to send from ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/BasicTransfer.cs"); Assert.True(compilationResult.Success); BuildCreateContractTransactionResponse preResponse = this.node1.SendCreateContractTransaction(compilationResult.Compilation, 0); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); decimal amount = 25; Money senderBalanceBefore = this.node1.WalletSpendableBalance; uint256 currentHash = this.node1.GetLastBlock().GetHash(); // Send amount to contract, which will send to contract address string[] parameters = new string[] { string.Format("{0}#{1}", (int)MethodParameterDataType.Address, receiveResponse.NewContractAddress) }; BuildCallContractTransactionResponse response = this.node1.SendCallContractTransaction( nameof(BasicTransfer.SendToAddress), preResponse.NewContractAddress, amount, parameters); this.mockChain.WaitAllMempoolCount(1); this.mockChain.MineBlocks(1); NBitcoin.Block lastBlock = this.node1.GetLastBlock(); // Blocks progressed Assert.NotEqual(currentHash, lastBlock.GetHash()); // Contract doesn't maintain any balance Assert.Equal((ulong)0, this.node1.GetContractBalance(preResponse.NewContractAddress)); // Receiver contract now has balance Assert.Equal((ulong)new Money((int)amount, MoneyUnit.BTC), this.node1.GetContractBalance(receiveResponse.NewContractAddress)); // Receiver contract stored to state Assert.Equal(new byte[] { 1 }, this.node1.GetStorageValue(receiveResponse.NewContractAddress, BasicReceive.ReceiveKey)); // Log was stored - bloom filter should be non-zero Assert.NotEqual(new Bloom(), ((ISmartContractBlockHeader)lastBlock.Header).LogsBloom); // Block contains a condensing transaction Assert.Equal(3, lastBlock.Transactions.Count); Transaction condensingTransaction = lastBlock.Transactions[2]; Assert.Single(condensingTransaction.Outputs); // Entire balance was forwarded byte[] toBytes = condensingTransaction.Outputs[0].ScriptPubKey.ToBytes(); Assert.Equal((byte)ScOpcodeType.OP_INTERNALCONTRACTTRANSFER, toBytes[0]); uint160 toAddress = new uint160(toBytes.Skip(1).ToArray()); Assert.Equal(receiveResponse.NewContractAddress, toAddress.ToBase58Address(this.node1.CoreNode.FullNode.Network)); Assert.Equal(new Money((long)amount, MoneyUnit.BTC), condensingTransaction.Outputs[0].Value); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); Assert.Equal(lastBlock.GetHash().ToString(), receipt.BlockHash); Assert.Equal(response.TransactionId.ToString(), receipt.TransactionHash); Assert.Single(receipt.Logs); Assert.Equal(receiveResponse.NewContractAddress, receipt.Logs[0].Address); Assert.True(receipt.Success); Assert.True(receipt.GasUsed > GasPriceList.BaseCost); Assert.Null(receipt.NewContractAddress); Assert.Equal(this.node1.MinerAddress.Address, receipt.From); Assert.Null(receipt.Error); Assert.Equal(preResponse.NewContractAddress, receipt.To); }
public static MnemonicReference Create ( ChainBase chain, Block block, int blockHeight, int txIndex, int txOutIndex) { var header = chain.GetBlock(blockHeight); if(header == null || block.GetHash() != header.HashBlock) throw new InvalidBrainAddressException("This block does not exists"); if(txIndex >= block.Transactions.Count) throw new InvalidBrainAddressException("The Transaction Index is out of the bound of the block"); var transaction = block.Transactions[txIndex]; return Create(chain, transaction, block, txOutIndex); }