adding send transaction raw with keys

This commit is contained in:
Dario Rekowski on RockPI 2020-04-03 11:33:21 +00:00
parent 8fc6cc89b9
commit 285a91353d
11 changed files with 303 additions and 14 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,73 @@
<?php
// in src/Form/ContactForm.php
namespace App\Form;
use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Validation\Validator;
class TransferRawForm extends Form
{
protected function _buildSchema(Schema $schema)
{
return $schema
->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 &gt; or &lt; 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;
}
}

View File

@ -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 "<br>";
//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);
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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('/([<>]|&gt;|&lt;|javascript:){1,}/', $value)) {

View File

@ -25,7 +25,7 @@ $this->assign('title', __('Schöpfungstransaktion'));
<?= $this->Form->control('receiver', ['options' => $address_options]); ?>
<!--<?= $this->Form->control('receiver_pubkey_hex', []) ?>-->
</fieldset>
<?= $this->Form->button(__('Transaktion(n) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?>
<?= $this->Form->button(__('Transaktion(en) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?>
<?= $this->Form->button(__('Weitere Transaktion erstellen'), ['name' => 'add', 'class' => 'grd-form-bn grd_clickable grd-width-200']) ?>
<?= $this->Form->end() ?>
</div>

View File

@ -105,7 +105,7 @@ $this->assign('title', __('Schöpfungstransaktion'));
<!--<?= $this->Form->control('receiver_pubkey_hex', []) ?>-->
</fieldset>
<div class="flowing-bottom">
<?= $this->Form->button(__('Transaktion(n) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?>
<?= $this->Form->button(__('Transaktion(en) abschließen'), ['name' => 'next', 'class' => 'grd-form-bn grd-form-bn-succeed grd_clickable grd-width-200']) ?>
<?= $this->Form->button(__('Weitere Transaktion erstellen'), ['name' => 'add', 'class' => 'grd-form-bn grd_clickable grd-width-200']) ?>
</div>
<?= $this->Form->end() ?>

View File

@ -0,0 +1,55 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
$this->assign('title', __('Überweisung'));
// In a View class
$this->loadHelper('Form', [
'templates' => 'ripple_horizontal_form',
]);
?>
<style type="text/css">
.showcase_content_area .invalid-feedback {
display:block;
}
</style>
<div class="row">
<div class="col-lg-11 col-md-12 equel-grid">
<div class="grid">
<p class="grid-header">Überweisen</p>
<div class="grid-body">
<div class="item-wrapper">
<div class="row mb-3">
<div class="col-lg-11 col-md-12 mx-auto">
<?= $this->Form->create($transferRawForm) ?>
<?= $this->Form->control('sender_privkey_hex', ['label' => __('Sender Private Key')]) ?>
<?= $this->Form->control('sender_pubkey_hex', ['label' => __('Sender Public Key')]) ?>
<?= $this->Form->control('receiver_pubkey_hex', ['label' => __('Empfänger Public Key')]) ?>
<?= $this->Form->control('memo', ['label' => __('Verwendungszweck'), 'rows' => 3]) ?>
<?= $this->Form->control('amount', ['label' => __('Betrag in GDD')]) ?>
<?= $this->Form->button(__('Transaktion abschließen'), ['name' => 'next', 'class' => 'btn btn-sm btn-primary']) ?>
<?= $this->Form->end() ?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?php // adding scripts vendor and core from ripple ui for validation effect ?>
<?= $this->Html->script(['core', 'vendor.addons']); ?>
<script type="text/javascript">
(function ($) {
'use strict';
$('textarea').maxlength({
alwaysShow: true,
warningClass: "badge mt-1 badge-success",
limitReachedClass: "badge mt-1 badge-danger"
});
})(jQuery);
</script>