public void NoBalance_TxValue0_TransferValue0() { uint160 contractAddress = new uint160(1); // No balance var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null); // No tx value var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(0); // No transfers var transfers = new List <TransferInfo>(); var result = new SmartContractExecutionResult(); Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transfers, false); // Ensure no state changes were made and no transaction has been added Assert.Null(internalTransaction); stateMock.Verify(x => x.SetUnspent(It.IsAny <uint160>(), It.IsAny <ContractUnspentOutput>()), Times.Never); }
public void NoBalance_TxValue1_TransferValue0() { uint160 contractAddress = new uint160(1); // No balance var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null); // 100 tx value var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(100); // No transfers var transfers = new List <TransferInfo>(); var result = new SmartContractExecutionResult(); Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transfers, false); // Ensure unspent was saved, but no condensing transaction was generated. Assert.Null(internalTransaction); stateMock.Verify(x => x.SetUnspent(contractAddress, It.IsAny <ContractUnspentOutput>())); }
public void HasBalance_TxValue0_TransferValue1() { uint160 contractAddress = new uint160(1); uint160 receiverAddress = new uint160(2); // Has balance var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState { CodeHash = new byte[32], StateRoot = new byte[32], TypeName = "Mock", UnspentHash = new byte[32] }); stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns(new ContractUnspentOutput { Hash = new uint256(1), Nvout = 1, Value = 100 }); // no tx value var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(0); txContextMock.SetupGet(p => p.Time).Returns(12345); // transfer 75 var transferInfos = new List <TransferInfo> { new TransferInfo { From = contractAddress, To = receiverAddress, Value = 75 } }; var result = new SmartContractExecutionResult(); // Condensing tx generated. 1 input. 2 outputs for each receiver and contract. Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false); Assert.NotNull(internalTransaction); Assert.Equal(txContextMock.Object.Time, internalTransaction.Time); Assert.Single(internalTransaction.Inputs); Assert.Equal(2, internalTransaction.Outputs.Count); Assert.Equal(new uint256(1), internalTransaction.Inputs[0].PrevOut.Hash); Assert.Equal((uint)1, internalTransaction.Inputs[0].PrevOut.N); string output1Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[0].ScriptPubKey).GetAddress(this.network).ToString(); Assert.Equal(receiverAddress.ToAddress(this.network).Value, output1Address); Assert.Equal(75, internalTransaction.Outputs[0].Value); Assert.True(internalTransaction.Outputs[1].ScriptPubKey.IsSmartContractInternalCall()); Assert.Equal(25, internalTransaction.Outputs[1].Value); // Ensure db updated stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 25)), Times.Once); }
public void Transfers_With_0Value() { // Scenario where contract was not sent any funds, but did make a method call with value 0. var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null); var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(0); var result = new SmartContractExecutionResult(); var transferInfos = new List <TransferInfo> { new TransferInfo { From = uint160.One, To = new uint160(2), Value = 0 } }; Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, uint160.One, txContextMock.Object, transferInfos, false); // No condensing transaction was generated. Assert.Null(internalTransaction); }
public void NoBalance_TxValue0_TransferValue1() { uint160 contractAddress = new uint160(1); uint160 receiverAddress = new uint160(2); // No balance var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null); // No tx value var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(0); // A transfer of 100 var transferInfos = new List <TransferInfo> { new TransferInfo { From = contractAddress, To = receiverAddress, Value = 100 } }; var result = new SmartContractExecutionResult(); // This should be impossible - contract has no existing balance and didn't get sent anything so it cannot send value. // TODO: Could be more informative exception Assert.ThrowsAny <Exception>(() => { Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false); }); }
public void NoBalance_TxValue1_TransferValue1() { uint160 contractAddress = new uint160(1); uint160 receiverAddress = new uint160(2); // No balance var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState { CodeHash = new byte[32], StateRoot = new byte[32], TypeName = "Mock", UnspentHash = new byte[32] }); stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns <ContractUnspentOutput>(null); // tx value 100 var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(100); txContextMock.SetupGet(p => p.TransactionHash).Returns(new uint256(123)); txContextMock.SetupGet(p => p.Nvout).Returns(1); txContextMock.SetupGet(p => p.Time).Returns(12345); // transfer 75 var transferInfos = new List <TransferInfo> { new TransferInfo(contractAddress, receiverAddress, 75) }; var result = new SmartContractExecutionResult(); // Condensing tx generated. 1 input from tx and 2 outputs - 1 for each contract and receiver Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false); Assert.NotNull(internalTransaction); Assert.Equal(txContextMock.Object.Time, internalTransaction.Time); Assert.Single(internalTransaction.Inputs); Assert.Equal(2, internalTransaction.Outputs.Count); Assert.Equal(txContextMock.Object.TransactionHash, internalTransaction.Inputs[0].PrevOut.Hash); Assert.Equal(txContextMock.Object.Nvout, internalTransaction.Inputs[0].PrevOut.N); string output1Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[0].ScriptPubKey).GetAddress(this.network).ToString(); Assert.Equal(receiverAddress.ToBase58Address(this.network), output1Address); Assert.Equal(75, internalTransaction.Outputs[0].Value); // Note outputs are in descending order by value. Assert.True(internalTransaction.Outputs[1].ScriptPubKey.IsSmartContractInternalCall()); Assert.Equal(25, internalTransaction.Outputs[1].Value); // Ensure db updated stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 25)), Times.Once); }
public void HasBalance_TxValue1_TransferValue0() { uint160 contractAddress = new uint160(1); // Has balance var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState { CodeHash = new byte[32], StateRoot = new byte[32], TypeName = "Mock", UnspentHash = new byte[32] }); stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns(new ContractUnspentOutput { Hash = new uint256(1), Nvout = 1, Value = 100 }); // tx value 100 var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(100); txContextMock.SetupGet(p => p.TransactionHash).Returns(new uint256(123)); txContextMock.SetupGet(p => p.Nvout).Returns(1); txContextMock.SetupGet(p => p.Time).Returns(12345); // no transfers var transferInfos = new List <TransferInfo>(); var result = new SmartContractExecutionResult(); // Condensing tx generated. 2 inputs. Current tx and stored spendable output. 1 output. Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false); Assert.NotNull(internalTransaction); Assert.Equal(txContextMock.Object.Time, internalTransaction.Time); Assert.Equal(2, internalTransaction.Inputs.Count); Assert.Single(internalTransaction.Outputs); Assert.Equal(txContextMock.Object.TransactionHash, internalTransaction.Inputs[0].PrevOut.Hash); Assert.Equal(txContextMock.Object.Nvout, internalTransaction.Inputs[0].PrevOut.N); Assert.Equal(new uint256(1), internalTransaction.Inputs[1].PrevOut.Hash); Assert.Equal((uint)1, internalTransaction.Inputs[1].PrevOut.N); Assert.True(internalTransaction.Outputs[0].ScriptPubKey.IsSmartContractInternalCall()); Assert.Equal(200, internalTransaction.Outputs[0].Value); // Ensure db updated stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 200)), Times.Once); }
public void TransferProcessor_NoBalance_NoTransfers() { // Scenario where contract was sent 0, doesn't yet have any UTXO assigned, and no transfers were made. var stateMock = new Mock <IContractState>(); stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null); var txContextMock = new Mock <ISmartContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(0); var result = new SmartContractExecutionResult(); Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, uint160.One, txContextMock.Object, new List <TransferInfo>(), false); // Ensure no state changes were made and no transaction has been added Assert.Null(internalTransaction); }
public void TransferProcessor_NoBalance_ReceivedFunds() { // Scenario where contract was sent some funds, doesn't yet have any UTXO assigned, and no transfers were made. var stateMock = new Mock <IContractStateRepository>(); stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null); var txContextMock = new Mock <ISmartContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(100); var result = new SmartContractExecutionResult(); this.transferProcessor.Process(stateMock.Object, uint160.One, txContextMock.Object, new List <TransferInfo>(), false); // Ensure unspent was saved, but no condensing transaction was generated. Assert.Null(result.InternalTransaction); stateMock.Verify(x => x.SetUnspent(new uint160(1), It.IsAny <ContractUnspentOutput>())); }
public void TransferProcessor_NoBalance_NoTransfers() { // Scenario where contract was sent 0, doesn't yet have any UTXO assigned, and no transfers were made. var carrierSkeleton = SmartContractCarrier.CallContract(1, new uint160(1), "Test", 1, (Gas)100_000); var transaction = new Transaction(); transaction.AddOutput(0, new Script(carrierSkeleton.Serialize())); var carrier = SmartContractCarrier.Deserialize(transaction); var stateMock = new Mock <IContractStateRepository>(); stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null); var txContextMock = new Mock <ISmartContractTransactionContext>(); var result = new SmartContractExecutionResult(); this.transferProcessor.Process(carrier, stateMock.Object, txContextMock.Object, new List <TransferInfo>(), false); // Ensure no state changes were made and no transaction has been added Assert.Null(result.InternalTransaction); }
public void TransferProcessor_NoBalance_ReceivedFunds() { // Scenario where contract was sent some funds, doesn't yet have any UTXO assigned, and no transfers were made. var carrierSkeleton = SmartContractCarrier.CallContract(1, new uint160(1), "Test", 1, (Gas)100_000); var transaction = new Transaction(); transaction.AddOutput(100, new Script(carrierSkeleton.Serialize())); var carrier = SmartContractCarrier.Deserialize(transaction); var stateMock = new Mock <IContractStateRepository>(); stateMock.Setup(x => x.GetCode(It.IsAny <uint160>())).Returns <byte[]>(null); var txContextMock = new Mock <ISmartContractTransactionContext>(); var result = new SmartContractExecutionResult(); this.transferProcessor.Process(carrier, stateMock.Object, txContextMock.Object, new List <TransferInfo>(), false); // Ensure unspent was saved, but no condensing transaction was generated. Assert.Null(result.InternalTransaction); stateMock.Verify(x => x.SetUnspent(new uint160(1), It.IsAny <ContractUnspentOutput>())); }
public void Transfers_Summed_Correctly() { uint160 contractAddress = new uint160(1); uint160 receiverAddress = new uint160(2); uint160 thirdAddress = new uint160(3); // Has balance var stateMock = new Mock <IStateRepository>(); stateMock.Setup(x => x.GetAccountState(contractAddress)).Returns(new AccountState { CodeHash = new byte[32], StateRoot = new byte[32], TypeName = "Mock", UnspentHash = new byte[32] }); stateMock.Setup(x => x.GetUnspent(contractAddress)).Returns(new ContractUnspentOutput { Hash = new uint256(1), Nvout = 1, Value = 100 }); // no tx value var txContextMock = new Mock <IContractTransactionContext>(); txContextMock.SetupGet(p => p.TxOutValue).Returns(0); txContextMock.SetupGet(p => p.Time).Returns(12345); // several transfers var transferInfos = new List <TransferInfo> { new TransferInfo(contractAddress, receiverAddress, 75), new TransferInfo(receiverAddress, contractAddress, 20), new TransferInfo(receiverAddress, thirdAddress, 5) }; // End result should be Contract: 45, Receiver: 50, ThirdAddress: 5 var result = new SmartContractExecutionResult(); // Condensing tx generated. 1 input. 3 outputs with consolidated balances. Transaction internalTransaction = this.transferProcessor.Process(stateMock.Object, contractAddress, txContextMock.Object, transferInfos, false); Assert.NotNull(internalTransaction); Assert.Equal(txContextMock.Object.Time, internalTransaction.Time); Assert.Single(internalTransaction.Inputs); Assert.Equal(3, internalTransaction.Outputs.Count); Assert.Equal(new uint256(1), internalTransaction.Inputs[0].PrevOut.Hash); Assert.Equal((uint)1, internalTransaction.Inputs[0].PrevOut.N); string output1Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[0].ScriptPubKey).GetAddress(this.network).ToString(); Assert.Equal(receiverAddress.ToBase58Address(this.network), output1Address); Assert.Equal(50, internalTransaction.Outputs[0].Value); Assert.True(internalTransaction.Outputs[1].ScriptPubKey.IsSmartContractInternalCall()); Assert.Equal(45, internalTransaction.Outputs[1].Value); string output3Address = PayToPubkeyHashTemplate.Instance.ExtractScriptPubKeyParameters(internalTransaction.Outputs[2].ScriptPubKey).GetAddress(this.network).ToString(); Assert.Equal(thirdAddress.ToBase58Address(this.network), output3Address); Assert.Equal(5, internalTransaction.Outputs[2].Value); // Ensure db updated stateMock.Verify(x => x.SetUnspent(contractAddress, It.Is <ContractUnspentOutput>(unspent => unspent.Value == 45)), Times.Once); }