Search in sources :

Example 16 with Role

use of com.icodici.universa.contract.roles.Role in project universa by UniversaBlockchain.

the class Reference method compareOperands.

/**
 *The comparison method for finding reference contract
 *
 * @param refContract contract to check for matching
 * @param leftOperand field_selector
 * @param rightOperand right operand  (constant | field_selector), constant = ("null" | number | string | true | false)
 * @param typeOfRightOperand type of right operand (constant | field_selector), constant = ("null" | number | string | true | false)
 * @param indxOperator index operator in array of operators
 * @param contracts contract list to check for matching
 * @param iteration check inside references iteration number
 * @return true if match or false
 */
public boolean compareOperands(Contract refContract, String leftOperand, String rightOperand, compareOperandType typeOfRightOperand, int indxOperator, Collection<Contract> contracts, int iteration) {
    boolean ret = false;
    Contract leftOperandContract = null;
    Contract rightOperandContract = null;
    Object left = null;
    Object right = null;
    double leftValD = 0;
    double rightValD = 0;
    long leftValL = 0;
    long rightValL = 0;
    boolean isLeftDouble = false;
    boolean isRightDouble = false;
    int firstPointPos;
    if (leftOperand.startsWith("ref.")) {
        leftOperand = leftOperand.substring(4);
        leftOperandContract = refContract;
    } else if (leftOperand.startsWith("this.")) {
        if (baseContract == null)
            throw new IllegalArgumentException("Use left operand in condition: " + leftOperand + ". But this contract not initialized.");
        leftOperand = leftOperand.substring(5);
        leftOperandContract = baseContract;
    } else if ((firstPointPos = leftOperand.indexOf(".")) > 0) {
        if (baseContract == null)
            throw new IllegalArgumentException("Use left operand in condition: " + leftOperand + ". But this contract not initialized.");
        Reference ref = baseContract.findReferenceByName(leftOperand.substring(0, firstPointPos));
        if (ref == null)
            throw new IllegalArgumentException("Not found reference: " + leftOperand.substring(0, firstPointPos));
        for (Contract checkedContract : contracts) if (ref.isMatchingWith(checkedContract, contracts, iteration + 1))
            leftOperandContract = checkedContract;
        if (leftOperandContract == null)
            return false;
        leftOperand = leftOperand.substring(firstPointPos + 1);
    } else
        throw new IllegalArgumentException("Invalid format of left operand in condition: " + leftOperand + ". Missing contract field.");
    if (rightOperand != null) {
        // if != null, rightOperand then FIELD or CONSTANT
        if (typeOfRightOperand == compareOperandType.FIELD) {
            // if typeOfRightOperand - FIELD
            if (rightOperand.startsWith("ref.")) {
                rightOperand = rightOperand.substring(4);
                rightOperandContract = refContract;
            } else if (rightOperand.startsWith("this.")) {
                if (baseContract == null)
                    throw new IllegalArgumentException("Use right operand in condition: " + rightOperand + ". But this contract not initialized.");
                rightOperand = rightOperand.substring(5);
                rightOperandContract = baseContract;
            } else if ((firstPointPos = rightOperand.indexOf(".")) > 0) {
                if (baseContract == null)
                    throw new IllegalArgumentException("Use right operand in condition: " + rightOperand + ". But this contract not initialized.");
                Reference ref = baseContract.findReferenceByName(rightOperand.substring(0, firstPointPos));
                if (ref == null)
                    throw new IllegalArgumentException("Not found reference: " + rightOperand.substring(0, firstPointPos));
                for (Contract checkedContract : contracts) if (ref.isMatchingWith(checkedContract, contracts, iteration + 1))
                    rightOperandContract = checkedContract;
                if (rightOperandContract == null)
                    return false;
                rightOperand = rightOperand.substring(firstPointPos + 1);
            } else
                throw new IllegalArgumentException("Invalid format of right operand in condition: " + rightOperand + ". Missing contract field.");
        }
        left = leftOperandContract.get(leftOperand);
        if (rightOperandContract != null)
            right = rightOperandContract.get(rightOperand);
        try {
            switch(indxOperator) {
                case LESS:
                case MORE:
                case LESS_OR_EQUAL:
                case MORE_OR_EQUAL:
                    if (left == null)
                        break;
                    if (typeOfRightOperand == compareOperandType.FIELD) {
                        // rightOperand is FIELD
                        if (right != null) {
                            if (isLeftDouble = isObjectMayCastToDouble(left))
                                leftValD = objectCastToDouble(left);
                            else
                                leftValL = objectCastToLong(left);
                            if (isRightDouble = isObjectMayCastToDouble(right))
                                rightValD = objectCastToDouble(right);
                            else
                                rightValL = objectCastToLong(right);
                            if (((indxOperator == LESS) && ((isLeftDouble ? leftValD : leftValL) < (isRightDouble ? rightValD : rightValL))) || ((indxOperator == MORE) && ((isLeftDouble ? leftValD : leftValL) > (isRightDouble ? rightValD : rightValL))) || ((indxOperator == LESS_OR_EQUAL) && ((isLeftDouble ? leftValD : leftValL) <= (isRightDouble ? rightValD : rightValL))) || ((indxOperator == MORE_OR_EQUAL) && ((isLeftDouble ? leftValD : leftValL) >= (isRightDouble ? rightValD : rightValL))))
                                ret = true;
                        }
                    } else if (typeOfRightOperand == compareOperandType.CONSTOTHER) {
                        // rightOperand is CONSTANT (null | number | true | false)
                        if (isLeftDouble = isObjectMayCastToDouble(left))
                            leftValD = objectCastToDouble(left);
                        else
                            leftValL = objectCastToLong(left);
                        if ((rightOperand != "null") && (rightOperand != "false") && (rightOperand != "true"))
                            if ((rightOperand.contains(".") && (((indxOperator == LESS) && ((isLeftDouble ? leftValD : leftValL) < Double.parseDouble(rightOperand))) || ((indxOperator == MORE) && ((isLeftDouble ? leftValD : leftValL) > Double.parseDouble(rightOperand))) || ((indxOperator == LESS_OR_EQUAL) && ((isLeftDouble ? leftValD : leftValL) <= Double.parseDouble(rightOperand))) || ((indxOperator == MORE_OR_EQUAL) && ((isLeftDouble ? leftValD : leftValL) >= Double.parseDouble(rightOperand))))) || (!rightOperand.contains(".") && (((indxOperator == LESS) && ((isLeftDouble ? leftValD : leftValL) < Long.parseLong(rightOperand))) || ((indxOperator == MORE) && ((isLeftDouble ? leftValD : leftValL) > Long.parseLong(rightOperand))) || ((indxOperator == LESS_OR_EQUAL) && ((isLeftDouble ? leftValD : leftValL) <= Long.parseLong(rightOperand))) || ((indxOperator == MORE_OR_EQUAL) && ((isLeftDouble ? leftValD : leftValL) >= Long.parseLong(rightOperand))))))
                                ret = true;
                    } else
                        throw new IllegalArgumentException("Invalid operator for string in condition: " + operators[indxOperator]);
                    break;
                case NOT_EQUAL:
                case EQUAL:
                    if (typeOfRightOperand == compareOperandType.FIELD) {
                        // rightOperand is FIELD
                        if ((left != null) && (right != null)) {
                            boolean isNumbers = true;
                            if (isLeftDouble = isObjectMayCastToDouble(left))
                                leftValD = objectCastToDouble(left);
                            else if (isObjectMayCastToLong(left))
                                leftValL = objectCastToLong(left);
                            else
                                isNumbers = false;
                            if (isNumbers) {
                                if (isRightDouble = isObjectMayCastToDouble(right))
                                    rightValD = objectCastToDouble(right);
                                else if (isObjectMayCastToLong(right))
                                    rightValL = objectCastToLong(right);
                                else
                                    isNumbers = false;
                            }
                            if (isNumbers && ((isLeftDouble && !isRightDouble) || (!isLeftDouble && isRightDouble))) {
                                if (((indxOperator == NOT_EQUAL) && ((isLeftDouble ? leftValD : leftValL) != (isRightDouble ? rightValD : rightValL))) || ((indxOperator == EQUAL) && ((isLeftDouble ? leftValD : leftValL) == (isRightDouble ? rightValD : rightValL))))
                                    ret = true;
                            } else if (((indxOperator == NOT_EQUAL) && !left.equals(right)) || ((indxOperator == EQUAL) && left.equals(right)))
                                ret = true;
                        }
                    } else if ((left != null) && (left.getClass().getName().endsWith("Role") || left.getClass().getName().endsWith("RoleLink"))) {
                        // if role - compare with address
                        try {
                            KeyAddress ka = new KeyAddress(rightOperand);
                            ret = ((Role) left).isMatchingKeyAddress(ka);
                        } catch (Exception e) {
                            throw new IllegalArgumentException("Address compare error in condition: " + e.getMessage());
                        }
                        if (indxOperator == NOT_EQUAL)
                            ret = !ret;
                    } else if (typeOfRightOperand == compareOperandType.CONSTOTHER) {
                        // rightOperand is CONSTANT (null|number|true|false)
                        if (!rightOperand.equals("null") && !rightOperand.equals("false") && !rightOperand.equals("true")) {
                            if (left != null) {
                                if (isObjectMayCastToDouble(left)) {
                                    leftValD = objectCastToDouble(left);
                                    Double leftDouble = new Double(leftValD);
                                    if ((rightOperand.contains(".") && (((indxOperator == NOT_EQUAL) && !leftDouble.equals(Double.parseDouble(rightOperand))) || ((indxOperator == EQUAL) && leftDouble.equals(Double.parseDouble(rightOperand))))) || (!rightOperand.contains(".") && (((indxOperator == NOT_EQUAL) && (leftValD != Long.parseLong(rightOperand))) || ((indxOperator == EQUAL) && (leftValD == Long.parseLong(rightOperand))))))
                                        ret = true;
                                } else {
                                    leftValL = objectCastToLong(left);
                                    Long leftLong = new Long(leftValL);
                                    if ((!rightOperand.contains(".") && (((indxOperator == NOT_EQUAL) && !leftLong.equals(Long.parseLong(rightOperand))) || ((indxOperator == EQUAL) && leftLong.equals(Long.parseLong(rightOperand))))) || (rightOperand.contains(".") && (((indxOperator == NOT_EQUAL) && (leftValL != Double.parseDouble(rightOperand))) || ((indxOperator == EQUAL) && (leftValL == Double.parseDouble(rightOperand))))))
                                        ret = true;
                                }
                            }
                        } else {
                            // if rightOperand : null|false|true
                            if (((indxOperator == NOT_EQUAL) && ((rightOperand.equals("null") && (left != null)) || (rightOperand.equals("true") && ((left != null) && !(boolean) left)) || (rightOperand.equals("false") && ((left != null) && (boolean) left)))) || ((indxOperator == EQUAL) && ((rightOperand.equals("null") && (left == null)) || (rightOperand.equals("true") && ((left != null) && (boolean) left)) || (rightOperand.equals("false") && ((left != null) && !(boolean) left)))))
                                ret = true;
                        }
                    } else if (typeOfRightOperand == compareOperandType.CONSTSTR) {
                        // rightOperand is CONSTANT (string)
                        if ((left != null) && (((indxOperator == NOT_EQUAL) && !left.equals(rightOperand)) || ((indxOperator == EQUAL) && left.equals(rightOperand))))
                            ret = true;
                    }
                    break;
                case MATCHES:
                    break;
                default:
                    throw new IllegalArgumentException("Invalid operator in condition");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("Error compare operands in condition: " + e.getMessage());
        }
    } else {
        // if rightOperand == null, then operation: defined / undefined
        if (indxOperator == DEFINED) {
            try {
                if (leftOperandContract.get(leftOperand) != null)
                    ret = true;
            } catch (Exception e) {
            }
        } else if (indxOperator == UNDEFINED) {
            try {
                ret = (leftOperandContract.get(leftOperand) == null);
            } catch (Exception e) {
                ret = true;
            }
        } else
            throw new IllegalArgumentException("Invalid operator in condition");
    }
    return ret;
}
Also used : Role(com.icodici.universa.contract.roles.Role) KeyAddress(com.icodici.crypto.KeyAddress)

Example 17 with Role

use of com.icodici.universa.contract.roles.Role in project universa by UniversaBlockchain.

the class ContractDelta method checkStateChange.

private void checkStateChange() throws Quantiser.QuantiserException {
    stateChanges = stateDelta.getChanges();
    stateChanges.remove("created_by");
    // todo: check siblings have different and proper branch ids
    stateChanges.remove("branch_id");
    // todo: these changes should be already checked
    stateChanges.remove("parent");
    stateChanges.remove("origin");
    if (insignificantKeys.containsAll(stateChanges.keySet())) {
        addError(BADSTATE, "", "new state is identical");
    }
    Role creator = changed.getRole("creator");
    if (creator == null) {
        addError(MISSING_CREATOR, "state.created_by", "");
        return;
    }
    ChangedItem<Integer, Integer> revision = (ChangedItem) stateChanges.get("revision");
    if (revision == null)
        addError(BAD_VALUE, "state.revision", "is not incremented");
    else {
        stateChanges.remove("revision");
        if (revision.oldValue() + 1 != revision.newValue())
            addError(BAD_VALUE, "state.revision", "wrong revision number");
    }
    Delta creationTimeChange = stateChanges.get("created_at");
    // if time is changed, it must be past:
    if (creationTimeChange != null) {
        stateChanges.remove("created_at");
        ChangedItem<ZonedDateTime, ZonedDateTime> ci = (ChangedItem) creationTimeChange;
        if (!ci.newValue().isAfter(ci.oldValue()))
            addError(BAD_VALUE, "state.created_at", "new creation datetime is before old one");
    }
    excludePermittedChanges();
    // Some changes coud be empty trees, cleared by permissions, which can not remove root
    // entries, so we should check them all:
    stateChanges.forEach((field, delta) -> {
        if (!delta.isEmpty()) {
            String reason = "";
            if (delta instanceof MapDelta)
                reason = " in " + ((MapDelta) delta).getChanges().keySet();
            addError(FORBIDDEN, "state." + field, "not permitted changes" + reason + ": " + delta.oldValue() + " -> " + delta.newValue());
        }
    });
}
Also used : Role(com.icodici.universa.contract.roles.Role) Delta(net.sergeych.diff.Delta) MapDelta(net.sergeych.diff.MapDelta) ZonedDateTime(java.time.ZonedDateTime) ChangedItem(net.sergeych.diff.ChangedItem) MapDelta(net.sergeych.diff.MapDelta)

Aggregations

Role (com.icodici.universa.contract.roles.Role)17 ListRole (com.icodici.universa.contract.roles.ListRole)10 SimpleRole (com.icodici.universa.contract.roles.SimpleRole)10 PublicKey (com.icodici.crypto.PublicKey)7 Test (org.junit.Test)7 PrivateKey (com.icodici.crypto.PrivateKey)6 HashSet (java.util.HashSet)5 ErrorRecord (com.icodici.universa.ErrorRecord)3 ChangeOwnerPermission (com.icodici.universa.contract.permissions.ChangeOwnerPermission)2 RoleLink (com.icodici.universa.contract.roles.RoleLink)2 ZonedDateTime (java.time.ZonedDateTime)2 ChangedItem (net.sergeych.diff.ChangedItem)2 KeyAddress (com.icodici.crypto.KeyAddress)1 Quantiser (com.icodici.universa.node2.Quantiser)1 Delta (net.sergeych.diff.Delta)1 MapDelta (net.sergeych.diff.MapDelta)1 Binder (net.sergeych.tools.Binder)1