remove wrongly positiend submodule

This commit is contained in:
Dario Rekowski on RockPI 2019-11-05 15:26:18 +00:00
parent c40c6b87a0
commit a35d88c424
17 changed files with 286 additions and 154 deletions

View File

@ -79,6 +79,14 @@ class DashboardController extends AppController
$stateUserQuery = $stateUserTable->find('all')->where(['public_key' => $public_key_bin]);
if($stateUserQuery->count() == 1) {
$stateUser = $stateUserQuery->first();
if($stateUser->first_name != $json['user']['first_name'] ||
$stateUser->last_name != $json['user']['last_name']) {
$stateUser->first_name = $json['user']['first_name'];
$stateUser->last_name = $json['user']['last_name'];
if(!$stateUserTable->save($stateUser)) {
$this->Flash->error(__('error updating state user ' . json_encode($stateUser->errors())));
}
}
$session->write('StateUser.id', $stateUser['id']);
//echo $stateUser['id'];
} else {
@ -86,7 +94,9 @@ class DashboardController extends AppController
$newStateUser->public_key = $public_key_bin;
$newStateUser->first_name = $json['user']['first_name'];
$newStateUser->last_name = $json['user']['last_name'];
$stateUserTable->save($newStateUser);
if(!$stateUserTable->save($newStateUser)) {
$this->Flash->error(__('error saving state user ' . json_encode($newStateUser->errors())));
}
$session->write('StateUser.id', $newStateUser->id);
//echo $newStateUser->id;
}

View File

@ -33,6 +33,9 @@ class StateUser extends Entity
'index_id' => true,
'state_group_id' => true,
'public_key' => true,
'email' => true,
'first_name' => true,
'last_name' => true,
'index' => true,
'state_group' => true,
'state_balances' => true,

View File

@ -37,6 +37,7 @@ class Transaction extends Entity
'state_group_id' => true,
'transaction_type_id' => true,
'tx_hash' => true,
'memo' => true,
'received' => true,
'state_group' => true,
'transaction_type' => true,

View File

@ -87,8 +87,11 @@ class TransactionsTable extends Table
->allowEmptyString('id', null, 'create');
$validator
->requirePresence('tx_hash', 'create')
->notEmptyString('tx_hash');
//->requirePresence('tx_hash', 'create')
->allowEmptyString('tx_hash', null, 'create');
$validator
->allowEmptyString('memo', null, 'create');
$validator
->dateTime('received')

View File

@ -10,57 +10,115 @@ namespace Model\Transactions;
//use Model\Messages\Gradido\Transaction;
//use Model\Messages\Gradido\TransactionBody;
use Cake\ORM\TableRegistry;
use Cake\Datasource\ConnectionManager;
class Transaction extends TransactionBase {
private $mProtoTransaction = null;
private $mProtoTransactionBody = null;
private $errors = [];
private $mTransactionBody = null;
public function __construct($base64Data) {
$transactionBin = base64_decode($base64Data);
if($transactionBin == FALSE) {
//$this->addError('base64 decode failed');
$this->addError(['data' => $base64Data, 'bin' => $transactionBin, 'msg' => 'base64 decode error']);
$this->addError('Transaction', ['data' => $base64Data, 'bin' => $transactionBin, 'msg' => 'base64 decode error']);
} else {
$this->mProtoTransaction = new \Model\Messages\Gradido\Transaction();
$this->mProtoTransaction->mergeFromString($transactionBin);
//echo 'serialize to json: <br>';
//echo $this->mProtoTransaction->serializeToJsonString();
$this->mProtoTransactionBody = new \Model\Messages\Gradido\TransactionBody();
$this->mProtoTransactionBody->mergeFromString($this->mProtoTransaction->getBodyBytes());
$data = $this->mProtoTransactionBody->getData();
var_dump($data);
$this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes());
}
}
public function getTransactionBody() {
return $this->mTransactionBody;
}
public function getFirstPublic() {
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
return $sigPairs[0]->getPubKey();
}
public function validate() {
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
$bodyBytes = $this->mProtoTransaction->getBodyBytes();
if(!$sigPairs || count($sigPairs) < 1) {
$this->addError('Transaction::validate', 'no signature found');
return false;
}
// check signature(s)
foreach($sigPairs as $sigPair) {
//echo 'sig Pair: '; var_dump($sigPair); echo "<br>";
$pubkey = $sigPair->getPubKey();
$signature = $sigPair->getEd25519();
if (!\Sodium\crypto_sign_verify_detached($signature, $bodyBytes, $pubkey)) {
$this->addError('signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' );
$this->addError('Transaction::validate', 'signature for key ' . bin2hex($pubkey) . ' isn\'t valid ' );
return false;
}
}
if(!$this->mTransactionBody->validate($sigPairs)) {
$this->addErrors($this->mTransactionBody->getErrors());
return false;
}
return true;
}
public function getErrors() {
return $this->errors;
public function save()
{
$connection = ConnectionManager::get('default');
$connection->begin();
//id transaction_id signature pubkey
if (!$this->mTransactionBody->save($this->getFirstPublic())) {
$this->addErrors($this->mTransactionBody->getErrors());
$connection->rollback();
return false;
}
// save transaction signatures
$transactionsSignaturesTable = TableRegistry::getTableLocator()->get('transaction_signatures');
$transactionId = $this->mTransactionBody->getTransactionID();
//signature pubkey
$sigPairs = $this->mProtoTransaction->getSigMap()->getSigPair();
echo "sigPairs: "; var_dump($sigPairs);
$signatureEntitys = [];
foreach($sigPairs as $sigPair) {
$signatureEntity = $transactionsSignaturesTable->newEntity();
$signatureEntity->transaction_id = $transactionId;
$signatureEntity->signature = $sigPair->getEd25519();
$signatureEntity->pubkey = $sigPair->getPubKey();
array_push($signatureEntitys, $signatureEntity);
}
//debug($signatureEntitys);
if(!$transactionsSignaturesTable->saveMany($signatureEntitys)) {
foreach($signatureEntitys as $entity) {
$errors = $entity->getErrors();
if(!$errors && count($errors) > 0) {
$pubkeyHex = bin2hex($entity->pubkey);
$this->addError('Transaction::save', 'error saving signature for pubkey: ' . $pubkeyHex . ', with errors: ' . json_encode($errors) );
}
}
$connection->rollback();
return false;
}
$connection->commit();
return true;
}
public function hasErrors() {
return count($this->errors) > 0;
}
private function addError($message) {
array_push($this->errors, $message);
}
}

View File

@ -2,6 +2,42 @@
namespace Model\Transactions;
use Cake\ORM\TableRegistry;
class TransactionBase {
private $errors = [];
public function getErrors() {
return errors;
}
public function addError($functionName, $errorName) {
array_push($this->errors, [$functionName => $errorName]);
}
public function addErrors($errors) {
$this->errors = array_merge($this->errors, $errors);
}
public function hasErrors() {
return count($this->errors) > 0;
}
protected function getStateUserId($publicKey) {
$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
$stateUser = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $publicKey])->first();
if($stateUser) {
return $stateUser->id;
}
// create new entry
$stateUserEntity = $stateUsersTable->newEntity();
$stateUserEntity->public_key = $publicKey;
if($stateUsersTable->save($stateUserEntity)) {
return $stateUserEntity->id;
} else {
$this->addError('TransactionBase::getStateUserId', 'error saving new state user with error: ' . json_encode($stateUserEntity->getErrors()));
}
return NULL;
}
}

View File

@ -2,6 +2,76 @@
namespace Model\Transactions;
use Cake\ORM\TableRegistry;
class TransactionBody extends TransactionBase {
private $mProtoTransactionBody = null;
private $mSpecificTransaction = null;
private $mTransactionID = 0;
public function __construct($bodyBytes) {
$this->mProtoTransactionBody = new \Model\Messages\Gradido\TransactionBody();
$this->mProtoTransactionBody->mergeFromString($bodyBytes);
switch($this->mProtoTransactionBody->getData()) {
case 'creation' : $this->mSpecificTransaction = new TransactionCreation($this->mProtoTransactionBody->getCreation()); break;
case 'transfer' : $this->mSpecificTransaction = new TransactionTransfer($this->mProtoTransactionBody->getTransfer()); break;
}
}
public function validate($sigPairs) {
if(!$this->mSpecificTransaction->validate($sigPairs)) {
$this->addErrors($this->mSpecificTransaction->getErrors());
return false;
}
return true;
}
public function getSpecificTransaction() {
return $this->mSpecificTransaction;
}
public function getMemo() {
return $this->mProtoTransactionBody->getMemo();
}
public function getTransactionTypeName()
{
return $this->mProtoTransactionBody->getData();
}
public function save($firstPublic) {
$transactionsTable = TableRegistry::getTableLocator()->get('transactions');
$transactionEntity = $transactionsTable->newEntity();
// transaction type id
$transactionTypesTable = TableRegistry::getTableLocator()->get('transaction_types');
$typeName = $this->getTransactionTypeName();
$transactionType = $transactionTypesTable->find('all')->where(['name' => $typeName])->select(['id'])->first();
if($transactionType == NULL) {
$this->addError('TransactionBody::save', 'zero type id for type: ' . $typeName);
return false;
}
$transactionEntity->transaction_type_id = $transactionType->id;
$transactionEntity->memo = $this->getMemo();
if ($transactionsTable->save($transactionEntity)) {
// success
$this->mTransactionID = $transactionEntity->id;
if(!$this->mSpecificTransaction->save($transactionEntity->id, $firstPublic)) {
$this->addErrors($this->mSpecificTransaction->getErrors());
return false;
}
} else {
$this->addError('TransactionBody::save', 'error saving transaction with: ' . json_encode($transactionEntity->getError()));
return false;
}
return true;
}
public function getTransactionID() {
return $this->mTransactionID;
}
}

View File

@ -4,6 +4,76 @@ namespace Model\Transactions;
//use App\Model\Transactions\TransactionBase;
use Cake\ORM\TableRegistry;
class TransactionCreation extends TransactionBase {
private $protoTransactionCreation;
private $transactionCreationsTable;
public function __construct($protoTransactionCreation) {
$this->protoTransactionCreation = $protoTransactionCreation;
$this->transactionCreationsTable = TableRegistry::getTableLocator()->get('transaction_creations');
}
public function getAmount() {
return $this->protoTransactionCreation->getReceiverAmount()->getAmount();
}
public function getReceiverPublic() {
return $this->protoTransactionCreation->getReceiverAmount()->getEd25519ReceiverPubkey();
}
public function getIdentHash() {
return $this->protoTransactionCreation->getIdentHash();
}
public function validate($sigPairs) {
// check if receiver public is not in signature list
$receiverPublic = $this->getReceiverPublic();
foreach($sigPairs as $sigPair) {
$pubkey = $sigPair->getPubKey();
if($pubkey == $receiverPublic) {
$this->addError('TransactionCreation::validate', 'receiver aren\'t allowed to sign creation Transaction');
return false;
}
}
// check if creation threshold for this month isn't reached
$existingCreations = $this->transactionCreationsTable
->find('all')
->group('ident_hash')
->where(['ident_hash' => $this->getIdentHash()]);
$existingCreations->select(['amount_sum' => $existingCreations->func()->sum('amount')]);
debug($existingCreations);
if($existingCreations->count() > 0) {
var_dump($existingCreations->toArray());
}
return true;
}
public function save($transaction_id, $firstPublic) {
$transactionCreationEntity = $this->transactionCreationsTable->newEntity();
$transactionCreationEntity->transaction_id = $transaction_id;
// state user id
$state_user_id = $this->getStateUserId($firstPublic);
if(!$state_user_id) {
$this->addError('TransactionCreation::save', 'couldn\'t get state user id');
return false;
}
$transactionCreationEntity->state_user_id = $state_user_id;
$transactionCreationEntity->amount = $this->getAmount();
$transactionCreationEntity->ident_hash = $this->getIdentHash();
if(!$this->transactionCreationsTable->save($transactionCreationEntity)) {
$this->addError('TransactionCreation::save', 'error saving transactionCreation with errors: ' . json_encode($transactionCreationEntity->getErrors()));
return false;
}
return true;
}
}

View File

@ -5,6 +5,18 @@ namespace Model\Transactions;
//use App\Model\Transactions\TransactionBase;
class TransactionTransfer extends TransactionBase {
private $protoTransactionTransfer;
public function __construct($protoTransactionTransfer) {
$this->protoTransactionTransfer = $protoTransactionTransfer;
}
public function validate($sigPairs) {
return true;
}
public function save($transaction_id, $firstPublic) {
return true;
}
}

View File

@ -40,7 +40,7 @@ $transactionPendings = $session->read('Transactions.pending');
<body>
<div class="versionstring dev-info">
<p class="grd_small">Community Server in Entwicklung</p>
<p class="grd_small">Alpha 0.4.4</p>
<p class="grd_small">Alpha 0.5.0</p>
</div>
<nav class="grd-left-bar expanded" data-topbar role="navigation">
<div class="grd-left-bar-section">

View File

@ -1,44 +0,0 @@
syntax = "proto3";
package model.messages.gradido;
message Key {
oneof key {
bytes ed25519 = 2; // ed25519 signature (libsodium default)
bytes ed25519_ref10 = 3; // ed25519 ref10 signature
}
}
message SignaturePair {
bytes pubKey = 1;
oneof signature {
bytes ed25519 = 2; // ed25519 signature (libsodium default)
bytes ed25519_ref10 = 3; // ed25519 ref10 signature
}
}
message SignatureMap {
repeated SignaturePair sigPair = 1; // Each signature pair corresponds to a unique Key required to sign the transaction.
}
/* An exact date and time. This is the same data structure as the protobuf Timestamp.proto (see the comments in https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto) */
message Timestamp {
int64 seconds = 1; // Number of complete seconds since the start of the epoch
int32 nanos = 2; // Number of nanoseconds since the start of the last second
}
/* An exact date and time, with a resolution of one second (no nanoseconds). */
message TimestampSeconds {
int64 seconds = 1; // Number of complete seconds since the start of the epoch
}
message SenderAmount {
bytes ed25519_sender_pubkey = 1;
sint64 amount = 2;
sint64 senderFinalBalance = 3; // sender balance after transaction, including perishability
}
message ReceiverAmount {
bytes ed25519_receiver_pubkey = 1;
sint64 amount = 2;
}

View File

@ -1,15 +0,0 @@
syntax = "proto3";
package model.messages.gradido;
import "BasicTypes.proto";
// need signature from this group and from parent (if it isn't zero)
message StateCreateGroup {
string name = 1;
Key groupPublicKey = 2;
Key parentGroupPublicKey = 3;
reserved "hederaConsensusId";
reserved 4;
}

View File

@ -1,12 +0,0 @@
syntax = "proto3";
package model.messages.gradido;
import "BasicTypes.proto";
// need signature from this group and from both parents (if it isn't zero)
message StateGroupChangeParent {
Key groupPublicKey = 1;
Key newParentGroupPublicKey = 2;
Key oldParentGroupPublicKey = 3;
}

View File

@ -1,19 +0,0 @@
syntax = "proto3";
package model.messages.gradido;
import "BasicTypes.proto";
/*
id will be set by Node server
txHash will be also set by Node server,
calculated from previous transaction txHash and this id, sigMap and received;
*/
message Transaction {
uint64 id = 1;
TimestampSeconds received = 2;
SignatureMap sigMap = 3;
bytes txHash = 4;
bytes bodyBytes = 5;
}

View File

@ -1,18 +0,0 @@
syntax = "proto3";
package model.messages.gradido;
import "Transfer.proto";
import "StateCreateGroup.proto";
import "StateGroupChangeParent.proto";
import "TransactionCreation.proto";
message TransactionBody {
string memo = 1; // max 150 chars
oneof data {
StateCreateGroup createGroup = 2;
StateGroupChangeParent groupChangeParent = 3;
Transfer transfer = 4;
TransactionCreation creation = 5;
}
}

View File

@ -1,13 +0,0 @@
syntax = "proto3";
package model.messages.gradido;
import "BasicTypes.proto";
// need signature from group admin or
// percent of group users another than the receiver
message TransactionCreation {
ReceiverAmount receiverAmount = 1;
sint32 ident_hash = 2;
}

View File

@ -1,10 +0,0 @@
syntax = "proto3";
package model.messages.gradido;
import "BasicTypes.proto";
message Transfer {
repeated SenderAmount senderAmounts = 1;
repeated ReceiverAmount receiverAmounts = 2;
}