/* * protected bool Validate(SignedTransaction signed, MultiSignature declaration) * { * MultiSignatureAddress multi; * if (MultiSignatureManager.TryGetAddress(declaration.Address, out multi)) * return false; * return true; * } */ // validates the inputs are spending money that exists public bool ValidateBalance(ILedgerState state, IEnumerable <TxInput> inputs) { // we cannot have duplicate (account + currency). In fact we can since we use fees in input var amounts = new Dictionary <AddressCurrency, Amount>(); foreach (var input in inputs) { var currency = input.Currency; var address = input.Address; // no need to check we have enough balance if we are issuer if (LiveService.IssuerManager.IsIssuer(currency, address)) { continue; } if (!state.TryGetAccount(address, out var account)) { return(false); } // TODO looks not good var key = new AddressCurrency(address, currency); var amount = amounts[key] = amounts.GetOrCreate(key, () => 0) + input.Amount; if (account.GetBalance(currency) < amount) { return(false); } } return(true); }
public override bool TryGetRequiredValidations(ILedgerState state, Address address, List <TxDeclaration> declarations, out TransactionRequiredValidation required) { switch (address.Type) { case AddressType.ECDSA: required = new AddressRequiredSignature(address); return(true); } required = null; return(false); }
public static bool TryGetDeclaration <T>(this ILedgerState state, Address address, out T declaration) where T : TxAddressDeclaration { // if the account does exists in the state if (!state.TryGetAccount(address, out var account)) { declaration = null; return(false); } // check the account has been declared declaration = account.GetDeclaration <T>(); return(declaration != null); }
public static bool TryGetRequiredValidations(ILedgerState state, TransactionRequiredValidationFactory factory, Transaction transaction, out List <TransactionRequiredValidation> validations) { var dictionary = new Dictionary <Address, TransactionRequiredValidation>(); foreach (var input in transaction.GetInputs()) { var address = input.Address; if (!dictionary.ContainsKey(address)) { TransactionRequiredValidation validation; if (!factory.TryGetRequiredValidations(state, input.Address, transaction.Declarations, out validation)) { validations = new List <TransactionRequiredValidation>(); return(false); } dictionary.Add(address, validation); } } validations = dictionary.Values.ToList(); return(true); }
private static bool TryGetRequiredSignatures(ILedgerState state, TransactionRequiredValidationFactory factory, Transaction transaction, out List <TransactionRequiredValidation> list) { var validations = new Dictionary <string, TransactionRequiredValidation>(); foreach (var input in transaction.GetInputs()) { if (!validations.ContainsKey(input.Address.Encoded)) { TransactionRequiredValidation required; if (!factory.TryGetRequiredValidations(state, input.Address, transaction.Declarations, out required)) { list = null; return(false); } validations.Add(input.Address.Encoded, required); } } list = validations.Values.ToList(); return(true); }
public static bool CheckSignatures(this SignedTransaction transaction, TransactionRequiredValidationFactory factory, Network network, long timestamp, ILedgerState state = null) { var hash = transaction.Hash; // get required signatures List <TransactionRequiredValidation> requireds; if (!TryGetRequiredValidations(state, factory, transaction.Transaction, out requireds)) { return(false); } var signatures = transaction.Signatures.Select(signature => new SignatureRequired(signature)).ToList(); // check required signatures and declarations are set foreach (var required in requireds) { if (!required.IsValid(signatures, transaction.Transaction, timestamp)) { return(false); } } // TODO we dont accept transactions with useless declarations // we try to optimize by checking signatures only at the end // verify signatures foreach (var signature in signatures) { // we dont accept transactions with useless signatures if (!signature.Required || !signature.Verify(hash, network)) { return(false); } } return(true); }
public abstract bool TryGetRequiredValidations(ILedgerState state, Address address, List <TxDeclaration> declarations, out TransactionRequiredValidation required);
// returns false if over the limit private bool TryGetRequiredValidationsRecursive(ILedgerState state, Address address, List <TxDeclaration> declarations, out TransactionRequiredValidation required, int depth) { // we check max depth to limit computation if (depth >= MAX_DEPTH) { required = null; return(false); } // try get account switch (address.Type) { case AddressType.ECDSA: required = new AddressRequiredSignature(address); break; case AddressType.MultiSignatureECDSA: if (!state.TryGetDeclaration <MultiSignature>(address, out var multi)) { if (!TryGetMultiSigFromDeclarations(declarations, address, out multi)) { required = NotDeclaredRequiredValidation.Instance; break; } } var list = new List <TransactionRequiredValidation>(); foreach (var signer in multi.Signers) { if (!TryGetRequiredValidationsRecursive(state, signer, declarations, out var required2, depth + 1)) { required = null; return(false); } list.Add(required2); } required = new MultiAddressRequiredSignature(multi, list); break; case AddressType.HashLock: if (!state.TryGetDeclaration <HashLock>(address, out var hashlock)) { if (!TryGetHashLockFromDeclarations(declarations, address, out hashlock)) { required = NotDeclaredRequiredValidation.Instance; break; } } required = new HashLockRequiredSignature(hashlock); break; case AddressType.TimeLock: if (!state.TryGetDeclaration <TimeLock>(address, out var timelock)) { if (!TryGetTimeLockFromDeclarations(declarations, address, out timelock)) { required = NotDeclaredRequiredValidation.Instance; break; } } required = new TimeLockRequiredSignature(timelock); //TODO break; case AddressType.VendingMachine: if (!state.TryGetDeclaration <VendingMachine>(address, out var machine)) { if (!TryGetVendingMachineFromDeclarations(declarations, address, out machine)) { required = NotDeclaredRequiredValidation.Instance; break; } } required = new VendingMachineRequiredSignature(machine); //TODO break; default: required = null; return(false); } return(true); }
public override bool TryGetRequiredValidations(ILedgerState state, Address address, List <TxDeclaration> declarations, out TransactionRequiredValidation required) { return(TryGetRequiredValidationsRecursive(state, address, declarations, out required, 0)); }