From 285a91353de8ae3c6f75976536a11490458cf831 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 3 Apr 2020 11:33:21 +0000 Subject: [PATCH] adding send transaction raw with keys --- .../Component/JsonRequestClientComponent.php | 33 +++++++++ src/Controller/StateBalancesController.php | 6 ++ .../TransactionSendCoinsController.php | 52 +++++++++++++ src/Form/TransferRawForm.php | 73 +++++++++++++++++++ src/Model/Transactions/SignatureMap.php | 20 +++++ src/Model/Transactions/Transaction.php | 50 ++++++++++--- src/Model/Transactions/TransactionBody.php | 16 ++++ .../Validation/TransactionValidation.php | 8 ++ src/Template/TransactionCreations/create.ctp | 2 +- .../TransactionCreations/create_multi.ctp | 2 +- .../TransactionSendCoins/create_raw.ctp | 55 ++++++++++++++ 11 files changed, 303 insertions(+), 14 deletions(-) create mode 100644 src/Form/TransferRawForm.php create mode 100644 src/Template/TransactionSendCoins/create_raw.ctp diff --git a/src/Controller/Component/JsonRequestClientComponent.php b/src/Controller/Component/JsonRequestClientComponent.php index e94151511..9f9559779 100644 --- a/src/Controller/Component/JsonRequestClientComponent.php +++ b/src/Controller/Component/JsonRequestClientComponent.php @@ -89,12 +89,45 @@ class JsonRequestClientComponent extends Component return ['state' => 'success', 'data' => $json]; } + public function sendRequestGDT($transactionBody, $url) { + + $http = new Client(); + $fullUrl = $this->getGDTServerUrl() . DS . $url; + $response = $http->post($this->getGDTServerUrl() . DS . $url, $transactionBody, ['type' => 'json']); + $responseStatus = $response->getStatusCode(); + if($responseStatus != 200) { + return [ + 'state' => 'error', + 'type' => 'request error', + 'msg' => 'server response status code isn\'t 200', + 'details' => $responseStatus, + 'fullUrl' => $fullUrl + ]; + } + //$responseType = $response->getType(); + //if($responseType != 'application/json') { +// return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t json', 'details' => $responseType]; +// } + $json = $response->getJson(); + if($json == null) { + //$responseType = $response->getType(); + return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json']; + } + return ['state' => 'success', 'data' => $json]; + } + static public function getLoginServerUrl() { $loginServer = Configure::read('LoginServer'); return $loginServer['host'] . ':' . $loginServer['port']; } + static public function getGDTServerUrl() + { + $gdtServer = Configure::read('GDTServer'); + return $gdtServer['host']; + } + static public function is_base64($s) { return (bool) preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s); diff --git a/src/Controller/StateBalancesController.php b/src/Controller/StateBalancesController.php index d823c9257..40329c2a3 100644 --- a/src/Controller/StateBalancesController.php +++ b/src/Controller/StateBalancesController.php @@ -19,6 +19,7 @@ class StateBalancesController extends AppController parent::initialize(); //$this->Auth->allow(['add', 'edit']); $this->Auth->allow(['overview']); + $this->loadComponent('JsonRequestClient'); } /** * Index method @@ -45,6 +46,11 @@ class StateBalancesController extends AppController return $result; } $user = $session->read('StateUser'); + // sendRequestGDT + // listPerEmailApi + + $gdtEntries = $this->JsonRequestClient->sendRequestGDT(['email' => $user['email']], 'GdtEntries' . DS . 'sumPerEmailApi'); + var_dump($gdtEntries); $creationsTable = TableRegistry::getTableLocator()->get('TransactionCreations'); $creationTransactions = $creationsTable diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index d3757a9ae..cffa7e2fd 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -10,8 +10,12 @@ use Cake\Routing\Router; use Cake\I18n\I18n; use App\Form\TransferForm; +use App\Form\TransferRawForm; use Model\Transactions\TransactionTransfer; +use Model\Transactions\TransactionBody; +use Model\Transactions\Transaction; + /** * TransactionSendCoins Controller * @@ -28,6 +32,7 @@ class TransactionSendCoinsController extends AppController $this->loadComponent('GradidoNumber'); //$this->Auth->allow(['add', 'edit']); $this->Auth->allow('create'); + $this->Auth->allow('createRaw'); } /** @@ -240,6 +245,53 @@ class TransactionSendCoinsController extends AppController $this->set('timeUsed', microtime(true) - $startTime); } + + public function createRaw() + { + $startTime = microtime(true); + $this->viewBuilder()->setLayout('frontend_ripple'); + + $transferRawForm = new TransferRawForm(); + $this->set('transferRawForm', $transferRawForm); + + if ($this->request->is('post')) { + $requestData = $this->request->getData(); + if($transferRawForm->validate($requestData)) { + $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); + $sender = ['priv' => $requestData['sender_privkey_hex'], 'pub' => $requestData['sender_pubkey_hex']]; + $reciver = ['pub' => $requestData['receiver_pubkey_hex']]; + + $builderResult = TransactionTransfer::build( + $amountCent, + $requestData['memo'], + $reciver['pub'], + $sender['pub'] + ); + if($builderResult['state'] === 'success') { + $protoTransaction = Transaction::build($builderResult['transactionBody'], $sender); + $transaction = new Transaction($protoTransaction); + if(!$transaction->validate()) { + $this->Flash->error(__('Error validating transaction')); + } else { + if(!$transaction->save()) { + $this->Flash->error(__('Error saving transaction')); + } else { + $this->Flash->success(__('Gradidos erfolgreich überwiesen!')); + } + } + } else { + $this->Flash->error(__('Error building transaction')); + } + + } + //var_dump($requestData); + // + //var_dump($data); + + } + + $this->set('timeUsed', microtime(true) - $startTime); + } /** * Delete method diff --git a/src/Form/TransferRawForm.php b/src/Form/TransferRawForm.php new file mode 100644 index 000000000..50c548ec5 --- /dev/null +++ b/src/Form/TransferRawForm.php @@ -0,0 +1,73 @@ +addField('sender_privkey_hex', ['type' => 'string']) + ->addField('sender_pubkey_hex', ['type' => 'string']) + ->addField('receiver_pubkey_hex', ['type' => 'string']) + ->addField('amount', ['type' => 'decimal', 'precision' => 2]) + ->addField('memo', ['type' =>'text', 'default' => '', 'rows' => 3, 'maxlength' => 150]); + } + + function validationDefault(Validator $validator) + { + $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation'); + + $validator + ->add('memo', 'length', [ + 'rule' => ['maxLength', 150], + 'message' => __('The memo should contain max 150 character') + ]) + ->add('memo', 'custom', [ + 'rule' => 'alphaNumeric', + 'provider' => 'custom', + //'message' => __('Only Alpha Numeric Character allowed') + 'message' => __('No HTML Tags like > or < please.') + ]) + ->allowEmptyString('memo', null, 'create') + ->add('receiver_pubkey_hex', 'custom', [ + 'rule' => 'hexKey64', + 'provider' => 'custom', + 'message' => 'a valid pubkey in hex format is required (64 character)' + ]) + ->add('sender_privkey_hex', 'custom', [ + 'rule' => 'hexKey128', + 'provider' => 'custom', + 'message' => 'a valid privkey in hex format is required (128 character)' + ]) + ->add('sender_pubkey_hex', 'custom', [ + 'rule' => 'hexKey64', + 'provider' => 'custom', + 'message' => 'a valid pubkey in hex format is required (64 character)' + ]) + ->add('amount', 'custom', [ + 'rule' => 'amount', + 'provider' => 'custom', + 'message' => __('Please give a valid positive number with maximal 2 decimal places') + ]); + return $validator; + } + /* + * $validator->add('title', 'custom', [ + 'rule' => 'customRule', + 'provider' => 'custom', + 'message' => 'The title is not unique enough' +]); + */ + + protected function _execute(array $data) + { + // Send an email. + return true; + } +} \ No newline at end of file diff --git a/src/Model/Transactions/SignatureMap.php b/src/Model/Transactions/SignatureMap.php index 0606182d3..d8cf35929 100644 --- a/src/Model/Transactions/SignatureMap.php +++ b/src/Model/Transactions/SignatureMap.php @@ -44,5 +44,25 @@ class SignatureMap { return new SignatureMap($protoSigMap); } + static public function build($bodyBytes, array $keys) + { + $protoSigMap = new \Model\Messages\Gradido\SignatureMap(); + $sigPairs = $protoSigMap->getSigPair(); + //echo "sigPairs: "; var_dump($sigPairs); echo "
"; + //return null; + + // sign with keys + foreach($keys as $key) { + $sigPair = new \Model\Messages\Gradido\SignaturePair(); + $sigPair->setPubKey(hex2bin($key['pub'])); + $sigPair->setEd25519(sodium_crypto_sign_detached($bodyBytes, hex2bin($key['priv']))); + + $sigPairs[] = $sigPair; + } + //array_push($sigPairs, $sigPair); + + return new SignatureMap($protoSigMap); + } + } \ No newline at end of file diff --git a/src/Model/Transactions/Transaction.php b/src/Model/Transactions/Transaction.php index cb7c4bee7..76353595a 100644 --- a/src/Model/Transactions/Transaction.php +++ b/src/Model/Transactions/Transaction.php @@ -20,21 +20,28 @@ class Transaction extends TransactionBase { - public function __construct($base64Data) { + public function __construct($base64Data) + { //$transactionBin = base64_decode($base64Data, true); //if($transactionBin == false) { //sodium_base64_VARIANT_URLSAFE_NO_PADDING - try { - $transactionBin = sodium_base642bin($base64Data, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); - } catch(\SodiumException $e) { - //$this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data); - //return; - $transactionBin = base64_decode($base64Data, true); - if($transactionBin == false) { - $this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data); - return; - } - } + if(is_a($base64Data, '\Model\Messages\Gradido\Transaction')) { + $this->mProtoTransaction = $base64Data; + $this->mTransactionBody = new TransactionBody($this->mProtoTransaction->getBodyBytes()); + return; + } + + try { + $transactionBin = sodium_base642bin($base64Data, SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING); + } catch(\SodiumException $e) { + //$this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data); + //return; + $transactionBin = base64_decode($base64Data, true); + if($transactionBin == false) { + $this->addError('Transaction', $e->getMessage());// . ' ' . $base64Data); + return; + } + } //*/} if($transactionBin == false) { @@ -62,6 +69,25 @@ class Transaction extends TransactionBase { } } + static public function build(\Model\Messages\Gradido\TransactionBody $transactionBody, $senderKeyPair) + { + $protoTransaction = new \Model\Messages\Gradido\Transaction(); + + $recevied = new \Model\Messages\Gradido\TimestampSeconds(); + $recevied->setSeconds(time()); + $protoTransaction->setReceived($recevied); + + $bodyBytes = $transactionBody->serializeToString(); + + $sigMap = SignatureMap::build($bodyBytes, [$senderKeyPair]); + $protoTransaction->setSigMap($sigMap->getProto()); + + $protoTransaction->setBodyBytes($bodyBytes); + + return $protoTransaction; + + } + public function getTransactionBody() { return $this->mTransactionBody; } diff --git a/src/Model/Transactions/TransactionBody.php b/src/Model/Transactions/TransactionBody.php index d2323b728..0dca15637 100644 --- a/src/Model/Transactions/TransactionBody.php +++ b/src/Model/Transactions/TransactionBody.php @@ -172,4 +172,20 @@ class TransactionBody extends TransactionBase { return $protoBody; } + static public function build($memo, $specificTransaction) + { + $protoBody = new \Model\Messages\Gradido\TransactionBody(); + $protoBody->setMemo($memo); + + if(is_a($specificTransaction, 'TransactionCreation')) { + $protoBody->setCreation($specificTransaction->getProto()); + } else if(is_a($specificTransaction, 'TransactionTransfer')) { + $protoBody->setTransfer($specificTransaction->getProto()); + } else { + return ['invalid tarnsaction type']; + } + return $protoBody; + + } + } diff --git a/src/Model/Validation/TransactionValidation.php b/src/Model/Validation/TransactionValidation.php index cea00f123..9705ef40b 100644 --- a/src/Model/Validation/TransactionValidation.php +++ b/src/Model/Validation/TransactionValidation.php @@ -31,6 +31,14 @@ class TransactionValidation return false; } + public static function hexKey128($value, array $context) { + if(strlen($value) != 128) return false; + if(preg_match('/^[[:xdigit:]]*$/', $value)) { + return true; + } + return false; + } + public static function alphaNumeric($value, array $context) { //if(preg_match('/^[a-zA-Z0-9äöüÄÖÜß _;:()-]\n\r*$/', $value)) { if(preg_match('/([<>]|>|<|javascript:){1,}/', $value)) { diff --git a/src/Template/TransactionCreations/create.ctp b/src/Template/TransactionCreations/create.ctp index 82ffe236b..a7e7c4afc 100644 --- a/src/Template/TransactionCreations/create.ctp +++ b/src/Template/TransactionCreations/create.ctp @@ -25,7 +25,7 @@ $this->assign('title', __('Schöpfungstransaktion')); Form->control('receiver', ['options' => $address_options]); ?> - Form->button(__('Transaktion(n) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?> + Form->button(__('Transaktion(en) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?> Form->button(__('Weitere Transaktion erstellen'), ['name' => 'add', 'class' => 'grd-form-bn grd_clickable grd-width-200']) ?> Form->end() ?> diff --git a/src/Template/TransactionCreations/create_multi.ctp b/src/Template/TransactionCreations/create_multi.ctp index c2bbfa656..c2ce22b4a 100644 --- a/src/Template/TransactionCreations/create_multi.ctp +++ b/src/Template/TransactionCreations/create_multi.ctp @@ -105,7 +105,7 @@ $this->assign('title', __('Schöpfungstransaktion'));
- Form->button(__('Transaktion(n) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?> + Form->button(__('Transaktion(en) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?> Form->button(__('Weitere Transaktion erstellen'), ['name' => 'add', 'class' => 'grd-form-bn grd_clickable grd-width-200']) ?>
Form->end() ?> diff --git a/src/Template/TransactionSendCoins/create_raw.ctp b/src/Template/TransactionSendCoins/create_raw.ctp new file mode 100644 index 000000000..0132c337f --- /dev/null +++ b/src/Template/TransactionSendCoins/create_raw.ctp @@ -0,0 +1,55 @@ +assign('title', __('Überweisung')); +// In a View class +$this->loadHelper('Form', [ + 'templates' => 'ripple_horizontal_form', +]); +?> + +
+
+
+

Überweisen

+
+
+
+
+ Form->create($transferRawForm) ?> + Form->control('sender_privkey_hex', ['label' => __('Sender Private Key')]) ?> + Form->control('sender_pubkey_hex', ['label' => __('Sender Public Key')]) ?> + Form->control('receiver_pubkey_hex', ['label' => __('Empfänger Public Key')]) ?> + Form->control('memo', ['label' => __('Verwendungszweck'), 'rows' => 3]) ?> + Form->control('amount', ['label' => __('Betrag in GDD')]) ?> + Form->button(__('Transaktion abschließen'), ['name' => 'next', 'class' => 'btn btn-sm btn-primary']) ?> + Form->end() ?> +
+
+
+
+
+
+
+ +Html->script(['core', 'vendor.addons']); ?> +