use of net.sergeych.diff.MapDelta in project universa by UniversaBlockchain.
the class ContractDelta method check.
// todo: need to test this synchronized attribute, should not affects overall node's concurrency
public synchronized void check() throws Quantiser.QuantiserException {
try {
BiMapper mapper = BossBiMapper.getInstance();
MapDelta rootDelta = Delta.between(mapper.serialize(existing), mapper.serialize(changed));
MapDelta definitionDelta = (MapDelta) rootDelta.getChange("definition");
stateDelta = (MapDelta) rootDelta.getChange("state");
if (definitionDelta != null) {
addError(ILLEGAL_CHANGE, "definition", "definition must not be changed");
}
// check immutable root area
// should be only one change here: state
int allowedRootChanges = 1;
Delta ch = rootDelta.getChange("api_level");
if (ch != null) {
allowedRootChanges++;
}
// or can be changed section "transactional"
Delta transactionalDelta = rootDelta.getChange("transactional");
if (transactionalDelta != null) {
allowedRootChanges++;
}
if (rootDelta.getChanges().size() > allowedRootChanges)
addError(ILLEGAL_CHANGE, "root", "root level changes are forbidden except the state");
// check only permitted changes in data
checkStateChange();
} catch (ClassCastException e) {
e.printStackTrace();
addError(FAILED_CHECK, "", "failed to compare, structure is broken or not supported");
}
}
use of net.sergeych.diff.MapDelta in project universa by UniversaBlockchain.
the class ChangeNumberPermission method checkChanges.
/**
* Check and remove changes that this permission allow. Note that it does not add errors itself,
* to allow using several such permission, from which some may allow the change, and some may not. If a check
* will add error, though, it will prevent subsequent permission objects to allow the change.
* @param contract source (valid) contract
* @param changed is contract for checking
* @param stateChanges map of changes, see {@link Delta} for details
*/
@Override
public void checkChanges(Contract contract, Contract changed, Map<String, Delta> stateChanges) {
MapDelta<String, Binder, Binder> dataChanges = (MapDelta<String, Binder, Binder>) stateChanges.get("data");
if (dataChanges == null)
return;
Delta delta = dataChanges.getChange(fieldName);
if (delta != null) {
if (!(delta instanceof ChangedItem))
return;
try {
int valueDelta = (int) delta.newValue() - (int) delta.oldValue();
if (valueDelta < minStep || valueDelta > maxStep)
return;
else {
newValue = (int) delta.newValue();
if (newValue > maxValue || newValue < minValue)
return;
else {
dataChanges.remove(fieldName);
}
}
} catch (Exception e) {
return;
}
}
}
use of net.sergeych.diff.MapDelta in project universa by UniversaBlockchain.
the class ModifyDataPermission method checkChanges.
/**
* checkChanges processes the map of changes with the list of fields with predefined data options for a role.
*
* @param contract source (valid) contract
* @param changedContract is contract for checking
* @param stateChanges map of changes, see {@link Delta} for details
*/
@Override
public void checkChanges(Contract contract, Contract changedContract, Map<String, Delta> stateChanges) {
Delta data = stateChanges.get("data");
if (data != null && data instanceof MapDelta) {
Map mapChanges = ((MapDelta) data).getChanges();
mapChanges.keySet().removeIf(key -> {
Object changed = mapChanges.get(key);
Object value = "";
if (changed != null && changed instanceof ChangedItem) {
value = ((ChangedItem) mapChanges.get(key)).newValue();
}
boolean containsField = this.fields.containsKey(key);
List<String> foundField = this.fields.get(key);
return (containsField && foundField == null) || (foundField != null && foundField.contains(value) || isEmptyOrNull(foundField, value));
});
}
}
use of net.sergeych.diff.MapDelta in project universa by UniversaBlockchain.
the class SplitJoinPermission method checkChanges.
/**
* Check and remove changes that this permission allow. Note that it does not add errors itself, to allow using
* several such permission, from which some may allow the change, and some may not. If a check will add error,
* though, it will prevent subsequent permission objects to allow the change.
*
* @param contract source (valid) contract
* @param changed is contract for checking
* @param stateChanges map of changes, see {@link Delta} for details
*/
@Override
public void checkChanges(Contract contract, Contract changed, Map<String, Delta> stateChanges) {
MapDelta<String, Binder, Binder> dataChanges = (MapDelta<String, Binder, Binder>) stateChanges.get("data");
if (dataChanges == null)
return;
Delta delta = dataChanges.getChange(fieldName);
if (delta != null) {
if (!(delta instanceof ChangedItem))
return;
try {
Decimal oldValue = new Decimal(delta.oldValue().toString());
Decimal newValue = new Decimal(delta.newValue().toString());
int cmp = oldValue.compareTo(newValue);
if (cmp > 0)
checkSplit(changed, dataChanges, oldValue, newValue);
else if (cmp < 0)
checkMerge(changed, dataChanges, newValue);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
use of net.sergeych.diff.MapDelta 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());
}
});
}
Aggregations