示例#1
0
 public RawEntryWithSaltedAndHashedEntry(PublicEntry rawEntry,
                                         byte[] salt,
                                         IHashProvider hashProvider)
 {
     RawEntry             = rawEntry;
     SaltedAndHashedEntry = hashProvider.ComputeMultiHash(rawEntry, salt).ToArray();
 }
        public void STTransactionEntryDao_STTransactionEntry_Should_Be_Convertible()
        {
            var stTransactionEntryDao = GetMapper <PublicEntryDao>();
            var pubKeyBytes           = new byte[30];

            new Random().NextBytes(pubKeyBytes);

            var original = new PublicEntry
            {
                Amount = 8855274.ToUint256ByteString(),
                Base   = new BaseEntry
                {
                    SenderPublicKey = pubKeyBytes.ToByteString(),
                    TransactionFees = UInt256.Zero.ToUint256ByteString()
                }
            };

            var transactionEntryDao = stTransactionEntryDao.ToDao(original);

            transactionEntryDao.Base.SenderPublicKey.Should().Be(pubKeyBytes.KeyToString());
            transactionEntryDao.Amount.Should().Be(8855274.ToString());

            var reconverted = transactionEntryDao.ToProtoBuff();

            reconverted.Base.TransactionFees.ToUInt256().Should().Be(UInt256.Zero);
            reconverted.Should().Be(original);
        }
示例#3
0
        public int Compare(PublicEntry x, PublicEntry y)
        {
            if (ReferenceEquals(x, y))
            {
                return(0);
            }

            if (ReferenceEquals(null, y))
            {
                return(1);
            }

            if (ReferenceEquals(null, x))
            {
                return(-1);
            }

            var feeComparison = x.TransactionFees.ToUInt256().CompareTo(y.TransactionFees.ToUInt256());

            if (feeComparison != 0)
            {
                return(feeComparison);
            }

            var timeStampComparison = y.Timestamp.CompareTo(x.Timestamp);

            if (timeStampComparison != 0)
            {
                return(timeStampComparison);
            }

            return(ByteUtil.ByteListMinSizeComparer.Default.Compare(x.Signature.ToByteArray(), y.Signature.ToByteArray()));
        }
示例#4
0
        private ExecutionEnvironment PrepareEnv(PublicEntry entry,
                                                Address sender,
                                                Address recipient,
                                                StateUpdate stateUpdate,
                                                bool isPrecompile)
        {
            var value       = entry.Amount.ToUInt256();
            var machineCode = entry.IsValidDeploymentEntry ? entry.Data.ToByteArray() : null;
            var data        = entry.IsValidDeploymentEntry ? null : entry.Data.ToByteArray();

            var env = new ExecutionEnvironment
            {
                Value            = value,
                TransferValue    = value,
                Sender           = sender,
                CodeSource       = recipient,
                ExecutingAccount = recipient,
                CurrentBlock     = stateUpdate,
                GasPrice         = entry.GasPrice.ToUInt256(),
                InputData        = data ?? new byte[0],
                CodeInfo         = isPrecompile
                    ? new CodeInfo(recipient)
                    : machineCode == null
                        ? _virtualMachine.GetCachedCodeInfo(recipient)
                        : new CodeInfo(machineCode),
                Originator = sender
            };

            return(env);
        }
示例#5
0
        public void PublicEntryDao_Should_Be_The_Same_When_Converted()
        {
            var pubKeyBytes = new byte[30];

            new Random().NextBytes(pubKeyBytes);
            var original = new PublicEntry
            {
                Amount = new byte[] { 222, 11, 107, 58, 118, 64, 0, 0 }.ToByteString(),
                SenderAddress = pubKeyBytes.ToByteString(),
                Signature     = new Signature
                {
                    RawBytes = new byte[] { 0x0 }.ToByteString(),
                SigningContext = new SigningContext
                    {
                        NetworkType = NetworkType.Devnet, SignatureType = SignatureType.TransactionPublic
                    }
                }
            };

            var transactionEntryDao1 = original.ToDao <PublicEntry, PublicEntryDao>(_mapperProvider);
            var hashId1 = transactionEntryDao1.Id;

            var reconverted = transactionEntryDao1.ToProtoBuff <PublicEntryDao, PublicEntry>(_mapperProvider);

            var transactionEntryDao2 = reconverted.ToDao <PublicEntry, PublicEntryDao>(_mapperProvider);
            var hashId2 = transactionEntryDao2.Id;

            hashId1.Should().Be(hashId2);
        }
        public void ValidateTransactionSignature_will_pass_with_valid_transaction_signature()
        {
            var subbedLogger         = Substitute.For <ILogger>();
            var cryptoContext        = new FfiWrapper();
            var transactionValidator = new TransactionValidator(subbedLogger, cryptoContext);

            // build a valid transaction
            var privateKey = cryptoContext.GeneratePrivateKey();

            var validTransaction = new PublicEntry
            {
                SenderAddress = privateKey.GetPublicKey().Bytes.ToByteString()
            };

            var signingContext = new SigningContext
            {
                NetworkType   = NetworkType.Devnet,
                SignatureType = SignatureType.TransactionPublic
            };

            var signature = new Signature
            {
                // sign an actual TransactionBroadcast object
                RawBytes = cryptoContext.Sign(privateKey, validTransaction.ToByteArray(), signingContext.ToByteArray())
                           .SignatureBytes.ToByteString(),
                SigningContext = signingContext
            };

            validTransaction.Signature = signature;

            var result = transactionValidator.ValidateTransaction(validTransaction);

            result.Should().BeTrue();
        }
示例#7
0
        TransactionValidator_ValidateTransactionSignature_returns_false_for_invalid_transaction_signature_verification()
        {
            var subbedLogger    = Substitute.For <ILogger>();
            var signatureResult = Substitute.For <ISignature>();
            var subbedContext   = new FakeContext(signatureResult, false);

            signatureResult.SignatureBytes.Returns(new byte[64]);

            var privateKey = Substitute.For <IPrivateKey>();

            // raw un-signed tx message
            var validTransaction = new PublicEntry
            {
                SenderAddress = privateKey.GetPublicKey().Bytes.ToByteString()
            };

            var txSig = new Signature
            {
                RawBytes = new byte[64]
                           .ToByteString(), //random bytes that are not of a signed TransactionBroadcast Object
                SigningContext = new SigningContext
                {
                    NetworkType   = NetworkType.Devnet,
                    SignatureType = SignatureType.TransactionPublic
                }
            };

            var transactionValidator = new TransactionValidator(subbedLogger, subbedContext);

            validTransaction.Signature = txSig;

            var result = transactionValidator.ValidateTransaction(validTransaction);

            result.Should().BeFalse();
        }
示例#8
0
        private bool ValidateTransactionSignature(PublicEntry transaction)
        {
            if (transaction.Signature.RawBytes == ByteString.Empty)
            {
                _logger.Error("Transaction signature is null");
                return(false);
            }

            var transactionSignature = _cryptoContext.GetSignatureFromBytes(transaction.Signature.RawBytes.ToByteArray(),
                                                                            transaction.SenderAddress.ToByteArray());

            var signingContext = transaction.Signature.SigningContext.ToByteArray();

            // we need to verify the signature matches the message, but transactionBroadcast contains the signature and original data,
            // passing message+sig will mean your verifying an incorrect message and always return false, so just null the sig.
            var transactionClone = transaction.Clone();

            transactionClone.Signature = null;

            if (_cryptoContext.Verify(transactionSignature, transactionClone.ToByteArray(), signingContext))
            {
                return(true);
            }

            _logger.Information(
                "Transaction Signature {signature} invalid.",
                transactionSignature);
            return(false);
        }
示例#9
0
        /// <summary>
        ///     This method calculates the basic gas cost of the <paramref name="entry" />
        ///     (excluding the cost of the VM execution).
        ///     The intrinsic cost is calculated as 21000 base cost + the entry data cost that is a function
        ///     of the number of bytes of data (and the cost of a single byte may differ between 0 bytes and non-0 bytes.
        /// </summary>
        /// <param name="entry"></param>
        /// <param name="releaseSpec"></param>
        /// <returns>Total intrinsic cost of the <paramref name="entry" /></returns>
        public static ulong CalculateIntrinsicGas(PublicEntry entry, IReleaseSpec releaseSpec)
        {
            ulong result = GasCostOf.Transaction; // the basic entry cost

            if (entry.Data != null)
            {
                // here is the difference between the 0 bytes and non-zero bytes cost
                // justified by a better compression level of zero bytes
                var txDataNonZeroGasCost = releaseSpec.IsEip2028Enabled
                    ? GasCostOf.TxDataNonZeroEip2028
                    : GasCostOf.TxDataNonZero;
                var length = entry.Data.Length;
                for (var i = 0; i < length; i++)
                {
                    result += entry.Data[i] == 0 ? GasCostOf.TxDataZero : (ulong)txDataNonZeroGasCost;
                }
            }

            if (entry.IsValidDeploymentEntry && releaseSpec.IsEip2Enabled)
            {
                result += GasCostOf.TxCreate;
            }

            return(result);
        }
示例#10
0
 public static Signature GenerateSignature(this PublicEntry publicEntry,
                                           ICryptoContext cryptoContext,
                                           IPrivateKey privateKey,
                                           SigningContext context)
 {
     return(GeneratePublicEntrySignature(publicEntry.Clone(), cryptoContext, privateKey, context));
 }
示例#11
0
 /// <summary>
 ///     @TODO we need to put this in some global logging system.
 /// </summary>
 /// <param name="entry"></param>
 /// <param name="reason"></param>
 private void TraceLogInvalidTx(PublicEntry entry, string reason)
 {
     if (_logger.IsEnabled(LogEventLevel.Verbose))
     {
         _logger.Verbose("Invalid entry {entry} ({reason})", entry, reason);
     }
 }
示例#12
0
        public void STTransactionEntryDao_STTransactionEntry_Should_Be_Convertible()
        {
            var pubKeyBytes = new byte[30];

            new Random().NextBytes(pubKeyBytes);

            var original = new PublicEntry
            {
                Amount          = 8855274.ToUint256ByteString(),
                SenderAddress   = pubKeyBytes.ToByteString(),
                TransactionFees = UInt256.Zero.ToUint256ByteString(),
                Signature       = new Signature
                {
                    RawBytes = new byte[] { 0x0 }.ToByteString(),
                SigningContext = new SigningContext
                    {
                        NetworkType = NetworkType.Devnet, SignatureType = SignatureType.TransactionPublic
                    }
                },
                Timestamp = Timestamp.FromDateTime(DateTime.UtcNow)
            };

            var transactionEntryDao = original.ToDao <PublicEntry, PublicEntryDao>(_mapperProvider);

            transactionEntryDao.SenderAddress.Should().Be(pubKeyBytes.KeyToString());
            transactionEntryDao.Amount.Should().Be(8855274.ToString());

            var reconverted = transactionEntryDao.ToProtoBuff <PublicEntryDao, PublicEntry>(_mapperProvider);

            reconverted.TransactionFees.ToUInt256().Should().Be(UInt256.Zero);
            reconverted.Should().Be(original);
        }
示例#13
0
        TransactionValidator_ValidateTransactionSignature_returns_true_for_valid_transaction_signature_verification()
        {
            var subbedLogger    = Substitute.For <ILogger>();
            var signatureResult = Substitute.For <ISignature>();
            var subbedContext   = new FakeContext(signatureResult, true);

            signatureResult.SignatureBytes.Returns(new byte[64]);

            var transactionValidator = new TransactionValidator(subbedLogger, subbedContext);
            var privateKey           = Substitute.For <IPrivateKey>();

            var validTransaction = new PublicEntry
            {
                SenderAddress = privateKey.GetPublicKey().Bytes.ToByteString()
            };

            var signature = new Signature
            {
                // sign an actual TransactionBroadcast object
                RawBytes = subbedContext.Sign(privateKey, validTransaction, new SigningContext())
                           .SignatureBytes.ToByteString(),
                SigningContext = new SigningContext
                {
                    NetworkType   = NetworkType.Devnet,
                    SignatureType = SignatureType.TransactionPublic
                }
            };

            validTransaction.Signature = signature;

            var result = transactionValidator.ValidateTransaction(validTransaction);

            result.Should().BeTrue();
        }
示例#14
0
        public int Compare(PublicEntry x, PublicEntry y)
        {
            if (ReferenceEquals(x, y))
            {
                return(0);
            }

            if (ReferenceEquals(null, y))
            {
                return(1);
            }

            if (ReferenceEquals(null, x))
            {
                return(-1);
            }

            var gasComparison = x.GasPrice.ToUInt256().CompareTo(y.GasPrice.ToUInt256());

            if (gasComparison != 0)
            {
                return(gasComparison);
            }

            return(ByteUtil.ByteListMinSizeComparer.Default.Compare(x.Signature.ToByteArray(), y.Signature.ToByteArray()));
        }
示例#15
0
 private static void QuickFail(PublicEntry entry, ExecutionEnvironment env, ITxTracer txTracer)
 {
     // here we need to propagate back to Delta
     env.CurrentBlock.GasUsed += (long)entry.GasLimit;
     if (txTracer.IsTracingReceipt)
     {
         txTracer.MarkAsFailed(env.ExecutingAccount, (long)entry.GasLimit, Bytes.Empty, "invalid");
     }
 }
示例#16
0
        public void Hashes_messages()
        {
            var hashProvider = _container.Resolve <IHashProvider>();
            var entry        = new PublicEntry();

            var arrayHash   = hashProvider.ComputeMultiHash(entry.ToByteArray());
            var messageHash = hashProvider.ComputeMultiHash(entry);

            arrayHash.ToArray().Should().BeEquivalentTo(messageHash.ToArray());
        }
示例#17
0
        private void UpdateLedgerAccountFromEntry(PublicEntry entry)
        {
            var pubKey = _cryptoContext.GetPublicKeyFromBytes(entry.Base.ReceiverPublicKey.ToByteArray());

            //todo: get an address from the key using the Account class from Common lib
            var account = Accounts.Get(pubKey.Bytes.ToBase32());

            //todo: a different logic for to and from entries
            account.Balance += entry.Amount.ToUInt256();
        }
示例#18
0
        private bool ValidateSender(PublicEntry entry, ExecutionEnvironment env, ITxTracer txTracer)
        {
            if (env.Sender != null)
            {
                return(true);
            }

            TraceLogInvalidTx(entry, "SENDER_NOT_SPECIFIED");
            QuickFail(entry, env, txTracer);
            return(false);
        }
示例#19
0
        /// <summary>
        /// Creates a delta for one off execution.
        /// </summary>
        public Delta CreateOneOffDelta(PublicEntry publicEntry)
        {
            Delta newDelta = Delta.Clone();

            newDelta.PreviousDeltaDfsHash = Cid.ToArray().ToByteString();
            newDelta.CoinbaseEntries.Clear();
            newDelta.ConfidentialEntries.Clear();
            newDelta.PublicEntries.Clear();
            newDelta.PublicEntries.Add(publicEntry);
            return(newDelta);
        }
示例#20
0
        private (Address sender, Address recipient) ExtractSenderAndRecipient(PublicEntry entry)
        {
            var sender    = entry.SenderAddress.ToAddress();
            var recipient = entry.ReceiverAddress.ToAddress();

            if (entry.IsValidDeploymentEntry)
            {
                recipient = ContractAddress.From(sender, _stateProvider.GetNonce(sender));
            }

            return(sender, recipient);
        }
示例#21
0
        public void Hashes_messages_with_suffix()
        {
            var hashProvider = _container.Resolve <IHashProvider>();
            var entry        = new PublicEntry();

            var suffix = new byte[1];

            var arrayHash   = hashProvider.ComputeMultiHash(entry.ToByteArray().Concat(suffix).ToArray());
            var messageHash = hashProvider.ComputeMultiHash(entry, suffix);

            arrayHash.ToArray().Should().BeEquivalentTo(messageHash.ToArray());
        }
示例#22
0
        private bool ValidateDeltaGasLimit(PublicEntry entry, ExecutionEnvironment env, ITxTracer txTracer)
        {
            if (entry.GasLimit <= (ulong)(env.CurrentBlock.GasLimit - env.CurrentBlock.GasUsed))
            {
                return(true);
            }

            TraceLogInvalidTx(entry,
                              $"BLOCK_GAS_LIMIT_EXCEEDED {entry.GasLimit.ToString()} > {env.CurrentBlock.GasLimit.ToString()} - {env.CurrentBlock.GasUsed.ToString()}");
            QuickFail(entry, env, txTracer);
            return(false);
        }
示例#23
0
        private bool ValidateNonce(PublicEntry entry, ExecutionEnvironment env, ITxTracer txTracer)
        {
            if (entry.Nonce == _stateProvider.GetNonce(env.Sender))
            {
                return(true);
            }

            TraceLogInvalidTx(entry,
                              $"WRONG_TRANSACTION_NONCE: {entry.Nonce.ToString()} (expected {_stateProvider.GetNonce(env.Sender).ToString()})");
            QuickFail(entry, env, txTracer);
            return(false);
        }
示例#24
0
        public void TestSigningForMessagesMethodEquivalence()
        {
            var privateKey = _wrapper.GeneratePrivateKey();

            var message1 = new PublicEntry {Nonce = 123};
            var message2 = new PublicEntry {Nonce = 34534908};

            var expected = _wrapper.Sign(privateKey, message1.ToByteArray(), message2.ToByteArray());
            var actual = _wrapper.Sign(privateKey, message1, message2);

            actual.SignatureBytes.Should().BeEquivalentTo(expected.SignatureBytes);
            actual.PublicKeyBytes.Should().BeEquivalentTo(expected.PublicKeyBytes);
        }
示例#25
0
        public void TestVerifyingForMessagesMethodEquivalence()
        {
            var privateKey = _wrapper.GeneratePrivateKey();

            var message1 = new PublicEntry {Nonce = 123};
            var context = new SigningContext {NetworkType = NetworkType.Mainnet};

            var signature = _wrapper.Sign(privateKey, message1.ToByteArray(), context.ToByteArray());

            var expected = _wrapper.Verify(signature, message1.ToByteArray(), context.ToByteArray());
            var actual = _wrapper.Verify(signature, message1, context);

            actual.Should().Be(expected);
        }
示例#26
0
        private (Address sender, Address recipient) ExtractSenderAndRecipient(PublicEntry entry)
        {
            var sender    = GetAccountAddress(entry.SenderAddress);
            var recipient = entry.TargetContract == null
                ? GetAccountAddress(entry.ReceiverAddress)
                : new Address(entry.TargetContract);

            if (entry.IsValidDeploymentEntry)
            {
                recipient = Address.OfContract(sender, _stateProvider.GetNonce(sender));
            }

            return(sender, recipient);
        }
示例#27
0
        private static Signature GeneratePublicEntrySignature(PublicEntry publicEntry,
                                                              ICryptoContext cryptoContext,
                                                              IPrivateKey privateKey,
                                                              SigningContext context)
        {
            publicEntry.Signature = null;
            var signatureBytes = cryptoContext.Sign(privateKey, publicEntry.ToByteArray(),
                                                    context.ToByteArray()).SignatureBytes;

            return(new Signature
            {
                RawBytes = signatureBytes.ToByteString(),
                SigningContext = context
            });
        }
示例#28
0
        public void TransactionValidator_ValidateTransactionSignature_returns_false_when_signature_is_null()
        {
            var subbedLogger  = Substitute.For <ILogger>();
            var subbedContext = Substitute.For <ICryptoContext>();

            var transactionValidator = new TransactionValidator(subbedLogger, subbedContext);

            var invalidSignature   = new Signature();
            var invalidTransaction = new PublicEntry {
                Signature = invalidSignature
            };

            var result = transactionValidator.ValidateTransaction(invalidTransaction);

            result.Should().BeFalse();
        }
示例#29
0
        public static PublicEntry Sign(this PublicEntry publicEntry,
                                       ICryptoContext cryptoContext,
                                       IPrivateKey privateKey,
                                       SigningContext context)
        {
            var clone = publicEntry.Clone();

            if (publicEntry.Signature?.RawBytes.Length == cryptoContext.SignatureLength)
            {
                Logger.Debug("The transaction was already signed, returning a clone.");
                return(clone);
            }

            clone.Signature = GeneratePublicEntrySignature(clone, cryptoContext, privateKey, context);
            return(clone);
        }
示例#30
0
        private bool ValidateSenderBalance(PublicEntry entry,
                                           ExecutionEnvironment env,
                                           ulong intrinsicGas,
                                           ITxTracer txTracer)
        {
            var senderBalance = _stateProvider.GetBalance(env.Sender);

            if (intrinsicGas * env.GasPrice + env.Value <= senderBalance)
            {
                return(true);
            }

            TraceLogInvalidTx(entry,
                              $"INSUFFICIENT_SENDER_BALANCE: ({env.Sender})_BALANCE = {senderBalance.ToString()}");
            QuickFail(entry, env, txTracer);
            return(false);
        }