use of com.icodici.universa.contract.roles.QuorumVoteRole in project universa by UniversaBlockchain.
the class Node method voteForContract.
public ZonedDateTime voteForContract(HashId votingItem, HashId candidateId, byte[] signature, List<Bytes> referencedItems, int quantaLimit) throws Exception {
return voteLock.synchronize(votingItem, lock -> {
VoteInfo votingInfo = ledger.getVotingInfo(votingItem);
if (votingInfo == null) {
throw new IllegalArgumentException("Voting " + votingItem + " doesn't exist");
}
if (!votingInfo.candidateIds.containsKey(candidateId)) {
throw new IllegalArgumentException("Candidate '" + candidateId + "' wasn't found in candidate list of voting " + votingItem);
}
PublicKey publicKey = ExtendedSignature.extractPublicKey(signature);
if (publicKey == null)
throw new IllegalArgumentException("Signature doesn't contain public key");
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(votingItem.getDigest());
outputStream.write(candidateId.getDigest());
byte[] data = outputStream.toByteArray();
if (ExtendedSignature.verify(publicKey, signature, data) == null) {
throw new IllegalArgumentException("Signature invalid");
}
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
Contract votingContract = votingInfo.contract;
String roleName = votingInfo.roleName;
long votingId = votingInfo.votingId;
ZonedDateTime expires = votingInfo.expires;
QuorumVoteRole role = votingContract.getRole(roleName).resolve();
if (role.isQuorumPercentageBased() && referencedItems != null && referencedItems.size() > 0) {
throw new IllegalArgumentException("Quorum of '" + role.getName() + "' is percentage based. It is not allowed to provide an additional referenced items voting such roles");
}
TransactionPack tp = votingContract.getTransactionPack();
if (referencedItems != null) {
for (Bytes ri : referencedItems) {
try {
tp.addReferencedItem(Contract.fromPackedTransaction(ri.getData()));
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
}
getServiceContracts().forEach((k, v) -> {
try {
Contract c = new Contract(v, tp);
tp.addReferencedItem(c);
tp.addTag(TransactionPack.TAG_PREFIX_RESERVED + k, c.getId());
} catch (IOException e) {
e.printStackTrace();
}
});
votingContract.getQuantiser().reset(quantaLimit);
try {
votingContract.prepareForReferenceMatching();
} catch (Quantiser.QuantiserException e) {
throw new Quantiser.QuantiserExceptionRuntime(e);
}
Set<PublicKey> keys = new HashSet<PublicKey>();
keys.add(publicKey);
List<KeyAddress> votes = role.getVotesForKeys(keys);
ledger.addVotes(votingId, votingInfo.candidateIds.get(candidateId), votes);
return expires;
});
}
use of com.icodici.universa.contract.roles.QuorumVoteRole in project universa by UniversaBlockchain.
the class Node method registerItem.
/**
* Asynchronous (non blocking) check/register for item from white list. If the item is new and eligible to process with the
* consensus, the processing will be started immediately. If it is already processing, the current state will be
* returned.
*
* If item is not signed by keys from white list will return {@link ItemResult#UNDEFINED}
*
* @param item to register/check state
* @param ubotSessionId id of ubot session item is registered within
*
* @return current (or last known) item state
*/
@NonNull
public ItemResult registerItem(Approvable item, HashId ubotSessionId) {
report(getLabel(), () -> concatReportMessage("register item: ", item.getId()), DatagramAdapter.VerboseLevel.BASE);
if (ubotSessionId != null && item instanceof Contract) {
Optional<UBotSessionProcessor> y = ubotSessionProcessors.values().stream().filter(sp -> sp.sessionId.equals(ubotSessionId)).findAny();
HashId ubotId = null;
if (y.isPresent()) {
Contract requestContract = y.get().requestContract;
HashId executableContractId = (HashId) requestContract.getStateData().get("executable_contract_id");
Contract ubotContract = requestContract.getTransactionPack().findContract(c -> c.getId().equals(executableContractId));
ubotId = ubotContract.getOrigin();
}
Contract contract = (Contract) item;
contract.getTransactionPack().setUbotId(ubotId);
Reference refUbotRegistry = new Reference(contract);
refUbotRegistry.name = "refUbotRegistry";
refUbotRegistry.setConditions(Binder.of("all_of", Do.listOf("ref.tag==\"universa:ubot_registry_contract\"")));
Reference refUbot = new Reference(contract);
refUbot.name = "refUbot";
refUbot.setConditions(Binder.of("all_of", Do.listOf("this.ubot==\"" + ubotId.toBase64String() + "\"")));
QuorumVoteRole role = new QuorumVoteRole("", contract, "refUbotRegistry.state.roles.ubots", getSessionQuorum(ubotSessionId));
role.addRequiredReference(refUbot, Role.RequiredMode.ALL_OF);
if (!contract.getCreator().resolve().equalsIgnoreName(role) || !contract.getReferences().get("refUbotRegistry").equalsIgnoreType(refUbotRegistry) || !contract.getReferences().get("refUbot").equalsIgnoreType(refUbot)) {
throw new IllegalArgumentException("Not a ubot pool contract.");
}
}
Object x = checkItemInternal(item.getId(), null, item, true, true);
if (x instanceof ItemProcessor && ubotSessionId != null) {
((ItemProcessor) x).setUbotSessionId(ubotSessionId);
}
ItemResult ir = (x instanceof ItemResult) ? (ItemResult) x : ((ItemProcessor) x).getResult();
report(getLabel(), () -> concatReportMessage("item processor for: ", item.getId(), " was created, state is ", ir.state), DatagramAdapter.VerboseLevel.BASE);
return ir;
// }
//
// report(getLabel(), () -> concatReportMessage("item: ", item.getId(), " not belongs to whitelist"),
// DatagramAdapter.VerboseLevel.BASE);
//
// return ItemResult.UNDEFINED;
}
use of com.icodici.universa.contract.roles.QuorumVoteRole in project universa by UniversaBlockchain.
the class UBotSessionsTest method createSession.
@Test
public void createSession() throws Exception {
TestSpace ts = prepareTestSpace();
// ts.nodes.forEach(m->m.node.setVerboseLevel(BASE));
int quorumSize = 4;
int poolSize = 5;
for (int k = 0; k < 1; k++) {
if (k != 0)
Thread.sleep(60 * 1000);
Contract executableContract = new Contract(TestKeys.privateKey(1));
executableContract.getStateData().put("cloud_methods", Binder.of("getRandom", Binder.of("pool", Binder.of("size", poolSize), "quorum", Binder.of("size", quorumSize))));
executableContract.getStateData().put("js", "simple JS code");
executableContract.seal();
Contract requestContract = new Contract(TestKeys.privateKey(2));
requestContract.getStateData().put("executable_contract_id", executableContract.getId());
requestContract.getStateData().put("method_name", "getRandom");
requestContract.getStateData().put("method_args", Do.listOf(1000));
requestContract.addNewItems(executableContract);
ContractsService.addReferenceToContract(requestContract, executableContract, "executable_contract_constraint", Reference.TYPE_EXISTING_DEFINITION, Do.listOf("ref.id==this.state.data.executable_contract_id"), true);
System.out.println(ts.client.command("ubotCreateSession", "packedRequest", requestContract.getPackedTransaction()));
AtomicReference<List<Integer>> pool = new AtomicReference<>();
AtomicInteger readyCounter = new AtomicInteger();
AsyncEvent readyEvent = new AsyncEvent();
HashId finalRequestId = requestContract.getId();
for (int i = 0; i < ts.clients.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
while (true) {
Binder res = ts.clients.get(finalI).command("ubotGetSession", "requestId", finalRequestId);
Thread.sleep(500);
if (res.get("session") != null && res.getBinderOrThrow("session").get("state") == null) {
continue;
}
if (res.get("session") != null && res.getBinderOrThrow("session").getString("state").equals("OPERATIONAL")) {
pool.set(res.getBinderOrThrow("session").getListOrThrow("sessionPool"));
if (readyCounter.incrementAndGet() == ts.clients.size()) {
readyEvent.fire();
}
break;
}
}
}).failure(new DeferredResult.Handler() {
@Override
public void handle(Object data) {
System.out.println("ERR: " + data);
}
});
}
readyEvent.await();
System.out.println(pool);
Set<Integer> poolQuorum = new HashSet<>();
while (poolQuorum.size() < quorumSize) {
poolQuorum.add(Do.sample(pool.get()));
}
Set<Client> quorumClients = new HashSet<>();
poolQuorum.forEach(n -> {
try {
quorumClients.add(new Client("./src/test_node_config_v2/test_node_config_v2.json", null, ubotKeys.get(n)));
} catch (IOException e) {
e.printStackTrace();
}
});
assertEquals(quorumClients.size(), poolQuorum.size());
HashId storageValue = HashId.createRandom();
quorumClients.forEach(c -> {
for (int i = 0; i < c.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
try {
// c.getClient(finalI).command("ubotUpdateStorage","requestId",requestContract.getId(),"storageName","default","fromValue",null,"toValue", storageValue);
c.getClient(finalI).command("ubotUpdateStorage", "requestId", finalRequestId, "storageName", "default", "toValue", storageValue);
} catch (IOException e) {
e.printStackTrace();
}
});
}
});
while (true) {
Binder res = ts.client.command("ubotGetStorage", "requestId", finalRequestId, "storageNames", Do.listOf("default"));
System.out.println(res);
if (res.getBinderOrThrow("current").get("default") != null && res.getBinderOrThrow("current").get("default").equals(storageValue) && (res.getBinderOrThrow("pending").get("default") == null || res.getBinderOrThrow("pending").getBinder("default").size() == 0)) {
break;
}
Thread.sleep(10);
}
HashId newStorageValue = HashId.createRandom();
quorumClients.forEach(c -> {
for (int i = 0; i < c.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
try {
// c.getClient(finalI).command("ubotUpdateStorage","executableContractId", executableContract.getId(),"storageName","default","fromValue",oldStorageValue,"toValue", newStorageValue);
c.getClient(finalI).command("ubotUpdateStorage", "requestId", finalRequestId, "storageName", "default", "toValue", newStorageValue);
} catch (IOException e) {
e.printStackTrace();
}
});
}
});
while (true) {
Binder res = ts.client.command("ubotGetStorage", "requestId", finalRequestId, "storageNames", Do.listOf("default"));
System.out.println(res);
if (res.getBinderOrThrow("current").get("default") != null && res.getBinderOrThrow("current").get("default").equals(newStorageValue) && (res.getBinderOrThrow("pending").get("default") == null || res.getBinderOrThrow("pending").getBinder("default").size() == 0)) {
break;
}
Thread.sleep(1000);
}
quorumClients.forEach(c -> {
for (int i = 0; i < c.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
try {
c.getClient(finalI).command("ubotCloseSession", "requestId", finalRequestId, "finished", true);
} catch (IOException e) {
e.printStackTrace();
}
});
}
});
AsyncEvent readyEvent2 = new AsyncEvent();
AtomicInteger readyCounter2 = new AtomicInteger();
for (int i = 0; i < ts.clients.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
while (true) {
Binder res = ts.clients.get(finalI).command("ubotGetSession", "requestId", finalRequestId);
Thread.sleep(500);
if (res.getBinder("session").get("state") == null) {
if (readyCounter2.incrementAndGet() == ts.clients.size()) {
readyEvent2.fire();
}
break;
}
}
}).failure(new DeferredResult.Handler() {
@Override
public void handle(Object data) {
System.out.println("ERR: " + data);
}
});
}
readyEvent2.await();
// new session
requestContract = new Contract(TestKeys.privateKey(2));
requestContract.getStateData().put("executable_contract_id", executableContract.getId());
requestContract.getStateData().put("method_name", "getRandom");
requestContract.getStateData().put("method_args", Do.listOf(1000));
ContractsService.addReferenceToContract(requestContract, executableContract, "executable_contract_constraint", Reference.TYPE_EXISTING_DEFINITION, Do.listOf("ref.id==this.state.data.executable_contract_id"), true);
System.out.println(ts.client.command("ubotCreateSession", "packedRequest", requestContract.getPackedTransaction()));
AtomicReference<List<Integer>> pool2 = new AtomicReference<>();
AtomicInteger readyCounter3 = new AtomicInteger();
AsyncEvent readyEvent3 = new AsyncEvent();
HashId finalRequestId2 = requestContract.getId();
AtomicReference<HashId> sessionId2 = new AtomicReference<>();
for (int i = 0; i < ts.clients.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
while (true) {
Binder res = ts.clients.get(finalI).command("ubotGetSession", "requestId", finalRequestId2);
Thread.sleep(500);
if (res.get("session") != null && res.getBinderOrThrow("session").get("state") == null) {
continue;
}
if (res.get("session") != null && res.getBinderOrThrow("session").getString("state").equals("OPERATIONAL")) {
sessionId2.set((HashId) res.getBinderOrThrow("session").get("sessionId"));
pool2.set(res.getBinderOrThrow("session").getListOrThrow("sessionPool"));
if (readyCounter3.incrementAndGet() == ts.clients.size()) {
readyEvent3.fire();
}
break;
}
}
}).failure(new DeferredResult.Handler() {
@Override
public void handle(Object data) {
System.out.println("ERR: " + data);
}
});
}
readyEvent3.await();
System.out.println(pool2);
System.out.println(sessionId2.get());
Set<Integer> poolQuorum2 = new HashSet<>();
while (poolQuorum2.size() < quorumSize) {
poolQuorum2.add(Do.sample(pool2.get()));
}
Set<Client> quorumClients2 = new HashSet<>();
poolQuorum2.forEach(n -> {
try {
quorumClients2.add(new Client("./src/test_node_config_v2/test_node_config_v2.json", null, ubotKeys.get(n)));
} catch (IOException e) {
e.printStackTrace();
}
});
assertEquals(quorumClients2.size(), poolQuorum.size());
HashId newStorageValue2 = HashId.createRandom();
quorumClients2.forEach(c -> {
for (int i = 0; i < c.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
try {
// c.getClient(finalI).command("ubotUpdateStorage","requestId",requestContract.getId(),"storageName","default","fromValue",newStorageValue,"toValue", newStorageValue2);
c.getClient(finalI).command("ubotUpdateStorage", "requestId", finalRequestId2, "storageName", "default", "toValue", newStorageValue2);
} catch (IOException e) {
e.printStackTrace();
}
});
}
});
while (true) {
Binder res = ts.client.command("ubotGetStorage", "requestId", requestContract.getId(), "storageNames", Do.listOf("default"));
System.out.println(res);
if (res.getBinderOrThrow("current").get("default") != null && res.getBinderOrThrow("current").get("default").equals(newStorageValue2) && (res.getBinderOrThrow("pending").get("default") == null || res.getBinderOrThrow("pending").getBinder("default").size() == 0)) {
break;
}
Thread.sleep(10);
}
HashId newStorageValue3 = HashId.createRandom();
quorumClients2.forEach(c -> {
for (int i = 0; i < c.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
try {
// c.getClient(finalI).command("ubotUpdateStorage","requestId",requestContract.getId(),"storageName","default","fromValue",oldStorageValue2,"toValue", newStorageValue3);
c.getClient(finalI).command("ubotUpdateStorage", "requestId", finalRequestId2, "storageName", "default", "toValue", newStorageValue3);
} catch (IOException e) {
e.printStackTrace();
}
});
}
});
while (true) {
Binder res = ts.client.command("ubotGetStorage", "requestId", requestContract.getId(), "storageNames", Do.listOf("default"));
System.out.println(res);
if (res.getBinderOrThrow("current").get("default") != null && res.getBinderOrThrow("current").get("default").equals(newStorageValue3) && (res.getBinderOrThrow("pending").get("default") == null || res.getBinderOrThrow("pending").getBinder("default").size() == 0)) {
break;
}
Thread.sleep(1000);
}
Contract contract = new Contract(TestKeys.privateKey(1));
Reference refUbotRegistry = new Reference(contract);
refUbotRegistry.name = "refUbotRegistry";
refUbotRegistry.setConditions(Binder.of("all_of", Do.listOf("ref.tag==\"universa:ubot_registry_contract\"")));
contract.addReference(refUbotRegistry);
Reference refUbot = new Reference(contract);
refUbot.name = "refUbot";
contract.getDefinition().getData().put("ubot", executableContract.getOrigin());
refUbot.setConditions(Binder.of("all_of", Do.listOf("this.ubot==\"" + executableContract.getOrigin().toBase64String() + "\"")));
contract.addReference(refUbot);
QuorumVoteRole role = new QuorumVoteRole("issuer", contract, "refUbotRegistry.state.roles.ubots", "" + quorumSize);
role.addRequiredReference(refUbot, Role.RequiredMode.ALL_OF);
contract.addRole(role);
contract.seal();
quorumClients2.forEach(c -> {
try {
for (int i = 0; i < c.size(); i++) {
c.getClient(i).command("ubotAddKeyToContract", "itemId", contract.getId(), "sessionId", sessionId2.get());
}
} catch (IOException e) {
e.printStackTrace();
}
});
Client randomClient2 = Do.sample(quorumClients2);
randomClient2.command("ubotApprove", "sessionId", sessionId2.get(), "packedItem", contract.getPackedTransaction());
ItemResult ir = randomClient2.getState(contract);
while (ir.state.isPending()) {
Thread.sleep(500);
ir = randomClient2.getState(contract);
}
System.out.println(ir);
assertEquals(ir.state, ItemState.APPROVED);
// session with parent and predefined pool
requestContract = new Contract(TestKeys.privateKey(1));
refUbotRegistry = new Reference(requestContract);
refUbotRegistry.name = "refUbotRegistry";
refUbotRegistry.setConditions(Binder.of("all_of", Do.listOf("ref.tag==\"universa:ubot_registry_contract\"")));
requestContract.addReference(refUbotRegistry);
refUbot = new Reference(requestContract);
refUbot.name = "refUbot";
refUbot.setConditions(Binder.of("all_of", Do.listOf("this.ubot==\"" + executableContract.getOrigin().toBase64String() + "\"")));
requestContract.addReference(refUbot);
role = new QuorumVoteRole("issuer", requestContract, "refUbotRegistry.state.roles.ubots", "" + quorumSize);
role.addRequiredReference(refUbot, Role.RequiredMode.ALL_OF);
requestContract.addRole(role);
requestContract.getStateData().put("predefined_pool", pool.get());
requestContract.getStateData().put("parent_session_id", sessionId2.get());
requestContract.getStateData().put("executable_contract_id", executableContract.getId());
requestContract.getStateData().put("method_name", "getRandom");
requestContract.getStateData().put("method_args", Do.listOf(1000));
ContractsService.addReferenceToContract(requestContract, executableContract, "executable_contract_constraint", Reference.TYPE_EXISTING_DEFINITION, Do.listOf("ref.id==this.state.data.executable_contract_id"), true);
Contract finalRequestContract = requestContract;
quorumClients2.forEach(c -> {
try {
for (int i = 0; i < c.size(); i++) {
c.getClient(i).command("ubotAddKeyToContract", "itemId", finalRequestContract.getId(), "sessionId", sessionId2.get());
}
} catch (IOException e) {
e.printStackTrace();
}
});
/*randomClient2.command("ubotApprove","sessionId", sessionId2.get(),"packedItem",requestContract.getPackedTransaction());
ir = randomClient2.getState(requestContract);
while(ir.state.isPending()) {
Thread.sleep(500);
ir = randomClient2.getState(requestContract);
}
System.out.println(ir);
assertEquals(ir.state,ItemState.APPROVED);*/
System.out.println(ts.client.command("ubotCreateSession", "packedRequest", requestContract.getPackedTransaction()));
AtomicInteger readyCounterX = new AtomicInteger();
AsyncEvent readyEventX = new AsyncEvent();
HashId finalRequestIdX = requestContract.getId();
AtomicReference<HashId> sessionIdX = new AtomicReference<>();
AtomicReference<List<Integer>> poolX = new AtomicReference<>();
for (int i = 0; i < ts.clients.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
while (true) {
Binder res = ts.clients.get(finalI).command("ubotGetSession", "requestId", finalRequestIdX);
Thread.sleep(500);
if (res.get("session") != null && res.getBinderOrThrow("session").get("state") == null) {
continue;
}
if (res.get("session") != null && res.getBinderOrThrow("session").getString("state").equals("OPERATIONAL")) {
sessionIdX.set((HashId) res.getBinderOrThrow("session").get("sessionId"));
poolX.set(res.getBinderOrThrow("session").getListOrThrow("sessionPool"));
if (readyCounterX.incrementAndGet() == ts.clients.size()) {
readyEventX.fire();
}
break;
}
}
}).failure(new DeferredResult.Handler() {
@Override
public void handle(Object data) {
System.out.println("ERR: " + data);
}
});
}
readyEventX.await();
assertEquals(poolX.get(), pool.get());
System.out.println(poolX);
Set<Integer> poolQuorumX = new HashSet<>();
while (poolQuorumX.size() < quorumSize) {
poolQuorumX.add(Do.sample(poolX.get()));
}
Set<Client> quorumClientsX = new HashSet<>();
poolQuorumX.forEach(n -> {
Client client = null;
while (client == null) {
try {
client = new Client("./src/test_node_config_v2/test_node_config_v2.json", null, ubotKeys.get(n));
} catch (ConnectException e) {
} catch (IOException e) {
e.printStackTrace();
}
}
quorumClientsX.add(client);
});
quorumClientsX.forEach(c -> {
for (int i = 0; i < c.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
try {
c.getClient(finalI).command("ubotCloseSession", "requestId", finalRequestIdX, "finished", true);
} catch (IOException e) {
e.printStackTrace();
}
});
}
});
AsyncEvent readyEventX2 = new AsyncEvent();
AtomicInteger readyCounterX2 = new AtomicInteger();
for (int i = 0; i < ts.clients.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
while (true) {
Binder res = ts.clients.get(finalI).command("ubotGetSession", "requestId", finalRequestIdX);
Thread.sleep(500);
if (res.getBinder("session").get("state") == null) {
if (readyCounterX2.incrementAndGet() == ts.clients.size()) {
readyEventX2.fire();
}
break;
}
}
}).failure(new DeferredResult.Handler() {
@Override
public void handle(Object data) {
System.out.println("ERR: " + data);
}
});
}
readyEventX2.await();
quorumClients2.forEach(c -> {
for (int i = 0; i < c.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
try {
c.getClient(finalI).command("ubotCloseSession", "requestId", finalRequestId2, "finished", true);
} catch (IOException e) {
e.printStackTrace();
}
});
}
});
AsyncEvent readyEvent4 = new AsyncEvent();
AtomicInteger readyCounter4 = new AtomicInteger();
for (int i = 0; i < ts.clients.size(); i++) {
int finalI = i;
Do.inParallel(() -> {
while (true) {
Binder res = ts.clients.get(finalI).command("ubotGetSession", "requestId", finalRequestId2);
Thread.sleep(500);
if (res.getBinder("session").get("state") == null) {
if (readyCounter4.incrementAndGet() == ts.clients.size()) {
readyEvent4.fire();
}
break;
}
}
}).failure(new DeferredResult.Handler() {
@Override
public void handle(Object data) {
System.out.println("ERR: " + data);
}
});
}
readyEvent4.await();
}
ts.shutdown();
}
Aggregations