public void Put(Block block) { var hash = block.Header.GetHash(); var position = _Store.Append(block); _Index.Put(hash.ToString(), position); _Index.Put(IndexedLimit, position); }
public MerkleBlock(Block block, uint256[] txIds) { header = block.Header; List<bool> vMatch = new List<bool>(); List<uint256> vHashes = new List<uint256>(); for(int i = 0 ; i < block.Transactions.Count ; i++) { var hash = block.Transactions[i].GetHash(); vHashes.Add(hash); vMatch.Add(txIds.Contains(hash)); } _PartialMerkleTree = new PartialMerkleTree(vHashes.ToArray(), vMatch.ToArray()); }
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); }
// Create from a CBlock, filtering transactions according to filter // Note that this will call IsRelevantAndUpdate on the filter for each transaction, // thus the filter will likely be modified. public MerkleBlock(Block block, BloomFilter filter) { header = block.Header; List<bool> vMatch = new List<bool>(); List<uint256> vHashes = new List<uint256>(); for(uint i = 0 ; i < block.Transactions.Count ; i++) { uint256 hash = block.Transactions[(int)i].GetHash(); vMatch.Add(filter.IsRelevantAndUpdate(block.Transactions[(int)i])); vHashes.Add(hash); } _PartialMerkleTree = new PartialMerkleTree(vHashes.ToArray(), vMatch.ToArray()); }
public Block GetBlock(uint256 blockId) { var ms = new MemoryStream(); var container = Configuration.GetBlocksContainer(); try { container.GetPageBlobReference(blockId.ToString()).DownloadToStream(ms); ms.Position = 0; Block b = new Block(); b.ReadWrite(ms, false); return b; } catch(StorageException ex) { if(ex.RequestInformation != null && ex.RequestInformation.HttpStatusCode == 404) { return null; } throw; } }
// Create from a CBlock, filtering transactions according to filter // Note that this will call IsRelevantAndUpdate on the filter for each transaction, // thus the filter will likely be modified. public MerkleBlock(Block block, BloomFilter filter) { header = block.Header; List<bool> vMatch = new List<bool>(); List<uint256> vHashes = new List<uint256>(); for(uint i = 0 ; i < block.Transactions.Length ; i++) { uint256 hash = block.Transactions[i].GetHash(); if(filter.IsRelevantAndUpdate(block.Transactions[i])) { vMatch.Add(true); vMatchedTxn.Add(Tuple.Create(i, hash)); } else vMatch.Add(false); vHashes.Add(hash); } txn = new PartialMerkleTree(vHashes.ToArray(), vMatch.ToArray()); }
public bool CheckBlock(Block block) { // These are checks that are independent of context // that can be verified before saving an orphan block. // Size limits var root = block.GetMerkleRoot(); if(block.Transactions.Count == 0 || block.Transactions.Count > MAX_BLOCK_SIZE || block.Length > MAX_BLOCK_SIZE) return DoS(100, Error("CheckBlock() : size limits failed"), RejectCode.INVALID, "bad-blk-length"); // Check proof of work matches claimed amount if(CheckProofOfWork && !CheckProofOfWorkCore(block)) return DoS(50, Error("CheckBlock() : proof of work failed"), RejectCode.INVALID, "high-hash"); // Check timestamp if(block.Header.BlockTime > Now + TimeSpan.FromSeconds(2 * 60 * 60)) return Invalid(Error("CheckBlock() : block timestamp too far in the future"), RejectCode.INVALID, "time-too-new"); // First transaction must be coinbase, the rest must not be if(block.Transactions.Count == 0 || !block.Transactions[0].IsCoinBase) return DoS(100, Error("CheckBlock() : first tx is not coinbase"), RejectCode.INVALID, "bad-cb-missing"); for(int i = 1 ; i < block.Transactions.Count ; i++) if(block.Transactions[i].IsCoinBase) return DoS(100, Error("CheckBlock() : more than one coinbase"), RejectCode.INVALID, "bad-cb-multiple"); // Check transactions foreach(var tx in block.Transactions) if(!CheckTransaction(tx)) return Error("CheckBlock() : CheckTransaction failed"); // Check for duplicate txids. This is caught by ConnectInputs(), // but catching it earlier avoids a potential DoS attack: HashSet<uint256> uniqueTx = new HashSet<uint256>(); for(int i = 0 ; i < block.Transactions.Count ; i++) { uniqueTx.Add(root.GetLeaf(i).Hash); } if(uniqueTx.Count != block.Transactions.Count) return DoS(100, Error("CheckBlock() : duplicate transaction"), RejectCode.INVALID, "bad-txns-duplicate", true); int nSigOps = 0; foreach(var tx in block.Transactions) { nSigOps += GetLegacySigOpCount(tx); } if(nSigOps > MAX_BLOCK_SIGOPS) return DoS(100, Error("CheckBlock() : out-of-bounds SigOpCount"), RejectCode.INVALID, "bad-blk-sigops", true); // Check merkle root if(CheckMerkleRoot && block.Header.HashMerkleRoot != root.Hash) return DoS(100, Error("CheckBlock() : hashMerkleRoot mismatch"), RejectCode.INVALID, "bad-txnmrklroot", true); return true; }
public Block CreateNextBlockWithCoinbase(PubKey pubkey, Money value, DateTimeOffset now) { Block block = new Block(); block.Header.Nonce = RandomUtils.GetUInt32(); block.Header.HashPrevBlock = this.GetHash(); block.Header.BlockTime = now; var tx = block.AddTransaction(new Transaction()); tx.AddInput(new TxIn() { ScriptSig = new Script(Op.GetPushOp(RandomUtils.GetBytes(30))) }); tx.Outputs.Add(new TxOut() { Value = value, ScriptPubKey = PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(pubkey) }); return block; }
public void WriteBlockHeader(BlockHeader header) { Block block = new Block(header); _HeaderStore.Put(block); }
public void InternalTransfer_ToContractAddress() { // 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.node1.WaitMempoolCount(1); this.node1.WaitForBlocksToBeMined(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.node1.WaitMempoolCount(1); this.node1.WaitForBlocksToBeMined(1); Assert.NotNull(this.node1.GetCode(preResponse.NewContractAddress)); double amount = 25; 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.node2.WaitMempoolCount(1); this.node2.WaitForBlocksToBeMined(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)); // Receipt is correct ReceiptResponse receipt = this.node1.GetReceipt(response.TransactionId.ToString()); 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 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 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 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); }
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 SmartContractsPoATest() { this.Name = "SmartContractsPoATest-0.13.0-beta"; this.NetworkType = NetworkType.Testnet; 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 genesisFederationMembers = new List <IFederationMember> { new FederationMember(new PubKey("03df4a360038a42b68aca8d198fc487c495ef9e4f3fe56daa6bbfdeea1a7cb5ec5")), new FederationMember(new PubKey("021c3e5b81a43284d166fb8862a9e7382630c2750f8556a4c7ba405ccdd70d4808")), new FederationMember(new PubKey("03a5055a77126a21b6d899482332bd9b2cc88fb96e83b172769754dee852a74316")), new FederationMember(new PubKey("03c9e8888a2d32b1022349a3bbf1aa325ed908f066bb0ebba8a1fe5eb6cabf3b7a")), new FederationMember(new PubKey("0282d9d0dcb978ecf1411c5cad744059ff75bdc9b352ab9454cf92ffe8cdf14789")), new FederationMember(new PubKey("02998a6d9a13446678e9f892c1fcc61834d1d439dd97d57fc9e30b51020d2277e4")), new FederationMember(new PubKey("037ab82c35af49860021e89c6868cd4a4b6f839cd1a3094dc828908ce9d86cf94a")) }; var consensusOptions = new PoAConsensusOptions( maxBlockBaseSize: 1_000_000, 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.RegisterMempoolRules(this.Consensus); }
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); }
/// <summary> /// Took the 'InitReg' from above and adjusted it slightly (set a static flag + removed the hash check) /// </summary> public SmartContractsRegTest() { this.CoinName = "SmartContracts"; this.NetworkName = "RegTest"; this.RootFolderName = StratisMain.StratisRootFolderName; this.DefaultConfigFilename = StratisMain.StratisDefaultConfigFilename; this.Magic = 0xDAB5BFFA; this.DefaultPort = 18444; this.DefaultMaxOutboundConnections = 16; this.DefaultMaxInboundConnections = 109; this.RPCPort = 18332; this.MaxTipAge = SmartContractNetwork.BitcoinDefaultMaxTipAgeInSeconds; this.MinTxFee = 1000; this.FallbackFee = 20000; this.MinRelayTxFee = 1000; this.MaxTimeOffsetSeconds = 25 * 60; var consensusFactory = new SmartContractPowConsensusFactory(); NBitcoin.Block genesisBlock = SmartContractNetwork.CreateGenesis(consensusFactory, 1296688602, 2, 0x207fffff, 1, Money.Coins(50m)); ((SmartContractBlockHeader)genesisBlock.Header).HashStateRoot = new uint256("21B463E3B52F6201C0AD6C991BE0485B6EF8C092E64583FFA655CC1B171FE856"); this.Genesis = genesisBlock; // Taken from StratisX. var consensusOptions = new PosConsensusOptions( maxBlockBaseSize: 1_000_000, maxStandardVersion: 2, maxStandardTxWeight: 100_000, maxBlockSigopsCost: 20_000, maxStandardTxSigopsCost: 20_000 / 5 ); var buriedDeployments = new BuriedDeploymentsArray { [BuriedDeployments.BIP34] = 100000000, [BuriedDeployments.BIP65] = 100000000, [BuriedDeployments.BIP66] = 100000000 }; var bip9Deployments = new NoBIP9Deployments(); this.Consensus = new NBitcoin.Consensus( consensusFactory: consensusFactory, consensusOptions: consensusOptions, coinType: default(int), hashGenesisBlock: genesisBlock.Header.GetHash(), subsidyHalvingInterval: 150, majorityEnforceBlockUpgrade: 750, majorityRejectBlockOutdated: 950, majorityWindow: 1000, buriedDeployments: buriedDeployments, bip9Deployments: bip9Deployments, bip34Hash: new uint256(), ruleChangeActivationThreshold: 108, // 95% of 2016 minerConfirmationWindow: 144, // nPowTargetTimespan / nPowTargetSpacing maxReorgLength: 500, defaultAssumeValid: null, // turn off assumevalid for regtest. maxMoney: long.MaxValue, coinbaseMaturity: 0, // Low to the point of being nonexistent to speed up integration tests. premineHeight: default(long), premineReward: Money.Zero, proofOfWorkReward: Money.Coins(50), powTargetTimespan: TimeSpan.FromSeconds(14 * 24 * 60 * 60), // two weeks powTargetSpacing: TimeSpan.FromSeconds(10 * 60), powAllowMinDifficultyBlocks: true, posNoRetargeting: true, powNoRetargeting: true, powLimit: new Target(new uint256("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")), minimumChainWork: uint256.Zero, isProofOfStake: default(bool), lastPowBlock: default(int), proofOfStakeLimit: null, proofOfStakeLimitV2: null, proofOfStakeReward: Money.Zero ); 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(); }
public async Task <(NBitcoin.Block, string)> MineNextBlockAsync(IEnumerable <NBitcoin.Transaction> transactions, bool throwOnError, NBitcoin.Block parentBlock, long parentBlockHeight) { var newBlock = parentBlock.CreateNextBlockWithCoinbase(new Key().PubKey, parentBlockHeight, NBitcoin.Altcoins.BCash.Instance.Regtest.Consensus.ConsensusFactory); newBlock.Transactions.AddRange(transactions); newBlock.Header.Bits = parentBlock.Header.Bits; // assume same difficulty target newBlock.Header.BlockTime = parentBlock.Header.BlockTime.AddSeconds(1); newBlock.UpdateMerkleRoot(); // Try to solve the block bool found = false; for (int i = 0; !found && i < 10000; i++) { newBlock.Header.Nonce = (uint)i; found = newBlock.Header.CheckProofOfWork(); } if (!found) { throw new Exception("Bad luck - unable to find nonce that matches required difficulty"); } var submitResult = await rpcClient0.SubmitBlock(newBlock.ToBytes()); if (!string.IsNullOrEmpty(submitResult) && throwOnError) { throw new Exception($"Error while submitting new block - submitBlock returned {submitResult}"); } return(newBlock, submitResult); }
public Task PutAsync(uint256 blockId, Block block) { return _Repository.PutAsync(blockId.ToString(), block); }
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 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); }
/// <inheritdoc/> public override void CheckBlockReward(RuleContext context, Money fees, int height, NBitcoin.Block block) { Money blockReward = fees + this.GetProofOfWorkReward(height); if (block.Transactions[0].TotalOut > blockReward) { this.Logger.LogTrace("(-)[BAD_COINBASE_AMOUNT]"); ConsensusErrors.BadCoinbaseAmount.Throw(); } }
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 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 WriteBlock(Block block) { WriteBlockHeader(block.Header); _BlockStore.Put(block); }
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 Block CreateNextBlockWithCoinbase(BitcoinAddress address, int height, DateTimeOffset now) { if (address == null) throw new ArgumentNullException("address"); Block block = new Block(); block.Header.Nonce = RandomUtils.GetUInt32(); block.Header.HashPrevBlock = this.GetHash(); block.Header.BlockTime = now; var tx = block.AddTransaction(new Transaction()); tx.AddInput(new TxIn() { ScriptSig = new Script(Op.GetPushOp(RandomUtils.GetBytes(30))) }); tx.Outputs.Add(new TxOut(address.Network.GetReward(height), address) { Value = address.Network.GetReward(height) }); return block; }
public SmartContractsPoARegTest() { this.Name = "SmartContractsPoARegTest"; 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 federationPubKeys = new List <PubKey> { this.FederationKeys[0].PubKey, // 029528e83f065153d7fa655e73a07fc96fc759162f1e2c8936fa592f2942f39af0 this.FederationKeys[1].PubKey, // 03b539807c64abafb2d14c52a0d1858cc29d7c7fad0598f92a1274789c18d74d2d // this.FederationKeys[2].PubKey // 02d6792cf941b68edd1e9056653573917cbaf974d46e9eeb9801d6fcedf846477a }; var consensusOptions = new PoAConsensusOptions( maxBlockBaseSize: 1_000_000, maxStandardVersion: 2, maxStandardTxWeight: 100_000, maxBlockSigopsCost: 20_000, maxStandardTxSigopsCost: 20_000 / 5, federationPublicKeys: federationPubKeys, targetSpacingSeconds: 3 ); 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: 0, // No max reorg limit on PoA networks. 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, 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 }
public static Block ParseJson(string json) { var formatter = new BlockExplorerFormatter(); var block = JObject.Parse(json); var txs = (JArray)block["tx"]; Block blk = new Block(); blk.Header.Bits = new Target((uint)block["bits"]); blk.Header.BlockTime = Utils.UnixTimeToDateTime((uint)block["time"]); blk.Header.Nonce = (uint)block["nonce"]; blk.Header.Version = (int)block["ver"]; blk.Header.HashPrevBlock = uint256.Parse((string)block["prev_block"]); blk.Header.HashMerkleRoot = uint256.Parse((string)block["mrkl_root"]); foreach (var tx in txs) { blk.AddTransaction(formatter.Parse((JObject)tx)); } return blk; }
/// <summary> /// Checks and computes stake. /// </summary> /// <param name="context">Context that contains variety of information regarding blocks validation and execution.</param> /// <exception cref="ConsensusErrors.PrevStakeNull">Thrown if previous stake is not found.</exception> /// <exception cref="ConsensusErrors.SetStakeEntropyBitFailed">Thrown if failed to set stake entropy bit.</exception> private void CheckAndComputeStake(RuleContext context) { this.Logger.LogTrace("()"); ChainedHeader chainedHeader = context.ValidationContext.ChainedHeader; NBitcoin.Block block = context.ValidationContext.Block; var posRuleContext = context as PosRuleContext; BlockStake blockStake = posRuleContext.BlockStake; // Verify hash target and signature of coinstake tx. if (BlockStake.IsProofOfStake(block)) { ChainedHeader prevChainedHeader = chainedHeader.Previous; BlockStake prevBlockStake = this.stakeChain.Get(prevChainedHeader.HashBlock); if (prevBlockStake == null) { ConsensusErrors.PrevStakeNull.Throw(); } // Only do proof of stake validation for blocks that are after the assumevalid block or after the last checkpoint. if (!context.SkipValidation) { this.stakeValidator.CheckProofOfStake(posRuleContext, prevChainedHeader, prevBlockStake, block.Transactions[1], chainedHeader.Header.Bits.ToCompact()); } else { this.Logger.LogTrace("POS validation skipped for block at height {0}.", chainedHeader.Height); } } // PoW is checked in CheckBlock(). if (BlockStake.IsProofOfWork(block)) { posRuleContext.HashProofOfStake = chainedHeader.Header.GetPoWHash(); } // Compute stake entropy bit for stake modifier. if (!blockStake.SetStakeEntropyBit(blockStake.GetStakeEntropyBit())) { this.Logger.LogTrace("(-)[STAKE_ENTROPY_BIT_FAIL]"); ConsensusErrors.SetStakeEntropyBitFailed.Throw(); } // Record proof hash value. blockStake.HashProof = posRuleContext.HashProofOfStake; int lastCheckpointHeight = this.Parent.Checkpoints.GetLastCheckpointHeight(); if (chainedHeader.Height > lastCheckpointHeight) { // Compute stake modifier. ChainedHeader prevChainedHeader = chainedHeader.Previous; BlockStake blockStakePrev = prevChainedHeader == null ? null : this.stakeChain.Get(prevChainedHeader.HashBlock); blockStake.StakeModifierV2 = this.stakeValidator.ComputeStakeModifierV2(prevChainedHeader, blockStakePrev, blockStake.IsProofOfWork() ? chainedHeader.HashBlock : blockStake.PrevoutStake.Hash); } else if (chainedHeader.Height == lastCheckpointHeight) { // Copy checkpointed stake modifier. CheckpointInfo checkpoint = this.Parent.Checkpoints.GetCheckpoint(lastCheckpointHeight); blockStake.StakeModifierV2 = checkpoint.StakeModifierV2; this.Logger.LogTrace("Last checkpoint stake modifier V2 loaded: '{0}'.", blockStake.StakeModifierV2); } else { this.Logger.LogTrace("POS stake modifier computation skipped for block at height {0} because it is not above last checkpoint block height {1}.", chainedHeader.Height, lastCheckpointHeight); } this.Logger.LogTrace("(-)[OK]"); }
public static MnemonicReference Parse (ChainBase chain, Wordlist wordList, string sentence, Transaction transaction, Block block) { return Parse(chain, wordList, sentence, transaction, block.Filter(transaction.GetHash())); }
/// <inheritdoc /> public override void CheckBlockReward(RuleContext context, Money fees, int height, NBitcoin.Block block) { this.Logger.LogTrace("({0}:{1},{2}:'{3}')", nameof(fees), fees, nameof(height), height); if (BlockStake.IsProofOfStake(block)) { var posRuleContext = context as PosRuleContext; Money stakeReward = block.Transactions[1].TotalOut - posRuleContext.TotalCoinStakeValueIn; Money calcStakeReward = fees + this.GetProofOfStakeReward(height); this.Logger.LogTrace("Block stake reward is {0}, calculated reward is {1}.", stakeReward, calcStakeReward); if (stakeReward > calcStakeReward) { this.Logger.LogTrace("(-)[BAD_COINSTAKE_AMOUNT]"); ConsensusErrors.BadCoinstakeAmount.Throw(); } } else { Money blockReward = fees + this.GetProofOfWorkReward(height); this.Logger.LogTrace("Block reward is {0}, calculated reward is {1}.", block.Transactions[0].TotalOut, blockReward); if (block.Transactions[0].TotalOut > blockReward) { this.Logger.LogTrace("(-)[BAD_COINBASE_AMOUNT]"); ConsensusErrors.BadCoinbaseAmount.Throw(); } } this.Logger.LogTrace("(-)"); }
public static MnemonicReference Create(ChainBase chain, Transaction transaction, Block block, int txOutIndex) { return Create(chain, transaction, block.Filter(transaction.GetHash()), txOutIndex); }
public Task PutAsync(Block block) { return PutAsync(block.GetHash(), block); }
public bool CheckProofOfWorkCore(Block block) { var target = block.Header.Bits; // Check range if(target <= new Target(0) || target > Network.ProofOfWorkLimit) return Error("CheckProofOfWork() : nBits below minimum work"); // Check proof of work matches claimed amount if(!block.Header.CheckProofOfWork()) return Error("CheckProofOfWork() : hash doesn't match nBits"); return true; }
public virtual async Task DoubleMerkleProofCheck() { _ = await CreateAndInsertTxAsync(true, true, 2); var node = NodeRepository.GetNodes().First(); var rpcClient = rpcClientFactoryMock.Create(node.Host, node.Port, node.Username, node.Password); long blockCount = await RpcClient.GetBlockCountAsync(); var blockHex = await RpcClient.GetBlockAsBytesAsync(await RpcClient.GetBestBlockHashAsync()); var firstBlock = NBitcoin.Block.Load(blockHex, Network.Main); rpcClientFactoryMock.AddKnownBlock(blockCount++, firstBlock.ToBytes()); PublishBlockHashToEventBus(await RpcClient.GetBestBlockHashAsync()); WaitUntilEventBusIsIdle(); var firstBlockHash = firstBlock.GetHash(); blockCount = await CreateAndPublishNewBlock(rpcClient, null); NBitcoin.Block forkBlock = null; var nextBlock = NBitcoin.Block.Load(await rpcClient.GetBlockByHeightAsBytesAsync(0), Network.Main); var pubKey = nextBlock.Transactions.First().Outputs.First().ScriptPubKey.GetDestinationPublicKeys().First(); // tx1 will be mined in block 1 and the notification has to be sent only once (1 insert into txBlock) var tx1 = Transaction.Parse(Tx1Hex, Network.Main); // tx2 will be mined in block 15 in chain 1 and in the block 20 in longer chain 2 and the notification // has to be sent twice (2 inserts into txBlock) var tx2 = Transaction.Parse(Tx2Hex, Network.Main); // Setup first chain, 20 blocks long do { var prevBlockHash = nextBlock.GetHash(); nextBlock = nextBlock.CreateNextBlockWithCoinbase(pubKey, new Money(50, MoneyUnit.MilliBTC), new ConsensusFactory()); nextBlock.Header.HashPrevBlock = prevBlockHash; if (blockCount == 1) { nextBlock.AddTransaction(tx1); } if (blockCount == 9) { forkBlock = nextBlock; } if (blockCount == 15) { nextBlock.AddTransaction(tx2); } nextBlock.Check(); rpcClientFactoryMock.AddKnownBlock(blockCount++, nextBlock.ToBytes()); }while (blockCount < 20); PublishBlockHashToEventBus(await rpcClient.GetBestBlockHashAsync()); nextBlock = forkBlock; blockCount = 10; // Setup second chain do { var prevBlockHash = nextBlock.GetHash(); nextBlock = nextBlock.CreateNextBlockWithCoinbase(pubKey, new Money(50, MoneyUnit.MilliBTC), new ConsensusFactory()); nextBlock.Header.HashPrevBlock = prevBlockHash; if (blockCount == 20) { nextBlock.AddTransaction(tx2); } nextBlock.Check(); rpcClientFactoryMock.AddKnownBlock(blockCount++, nextBlock.ToBytes()); }while (blockCount < 21); PublishBlockHashToEventBus(await rpcClient.GetBestBlockHashAsync()); var merkleProofs = (await TxRepositoryPostgres.GetTxsToSendMerkleProofNotificationsAsync(0, 100)).ToArray(); Assert.AreEqual(3, merkleProofs.Length); Assert.IsTrue(merkleProofs.Count(x => new uint256(x.TxExternalId).ToString() == Tx1Hash) == 1); // Tx2 must have 2 requests for merkle proof notification (blocks 15 and 20) Assert.IsTrue(merkleProofs.Count(x => new uint256(x.TxExternalId).ToString() == Tx2Hash) == 2); Assert.IsTrue(merkleProofs.Any(x => new uint256(x.TxExternalId).ToString() == Tx2Hash && x.BlockHeight == 15)); Assert.IsTrue(merkleProofs.Any(x => new uint256(x.TxExternalId).ToString() == Tx2Hash && x.BlockHeight == 20)); }