Skip to content
Snippets Groups Projects
Commit 5dc33eaa authored by Moul's avatar Moul
Browse files

[enh] #390, #396: Implement generic send_document()

Use it in cert, membership, and tx cmds
With urllib, the 200 error is no longer returned but an exception
TODO: write test_send_document()
parent a9c902ed
No related branches found
No related tags found
1 merge request!182#390, #396, #407: Drop async, send_doc(), Documents BBC
...@@ -24,12 +24,12 @@ from tabulate import tabulate ...@@ -24,12 +24,12 @@ from tabulate import tabulate
from silkaj import tui, wot from silkaj import tui, wot
from silkaj import wot_tools as wt from silkaj import wot_tools as wt
from silkaj.auth import auth_method from silkaj.auth import auth_method
from silkaj.tools import message_exit
from silkaj.network_tools import ClientInstance
from silkaj.blockchain_tools import BlockchainParams, HeadBlock from silkaj.blockchain_tools import BlockchainParams, HeadBlock
from silkaj.constants import ALL, DATE, SUCCESS_EXIT_STATUS from silkaj.constants import ALL, DATE, SUCCESS_EXIT_STATUS
from silkaj.crypto_tools import is_pubkey_and_check from silkaj.crypto_tools import is_pubkey_and_check
from silkaj.license import license_approval from silkaj.license import license_approval
from silkaj.network_tools import ClientInstance, send_document
from silkaj.tools import message_exit
@click.command("cert", help="Send certification") @click.command("cert", help="Send certification")
...@@ -78,12 +78,7 @@ def send_certification(ctx, uid_pubkey_to_certify): ...@@ -78,12 +78,7 @@ def send_certification(ctx, uid_pubkey_to_certify):
certification.sign([key]) certification.sign([key])
# Send certification document # Send certification document
response = client(bma.wot.certify, certification.signed_raw()) send_document(bma.wot.certify, certification)
if response.status == 200:
print("Certification successfully sent.")
else:
print("Error while publishing certification: {}".format(response.text()))
def pre_checks(client, issuer_pubkey, pubkey_to_certify): def pre_checks(client, issuer_pubkey, pubkey_to_certify):
......
...@@ -26,7 +26,7 @@ from silkaj import auth, tui, wot ...@@ -26,7 +26,7 @@ from silkaj import auth, tui, wot
from silkaj.blockchain_tools import BlockchainParams, HeadBlock from silkaj.blockchain_tools import BlockchainParams, HeadBlock
from silkaj.constants import DATE, SUCCESS_EXIT_STATUS from silkaj.constants import DATE, SUCCESS_EXIT_STATUS
from silkaj.license import license_approval from silkaj.license import license_approval
from silkaj.network_tools import ClientInstance from silkaj.network_tools import ClientInstance, send_document
@click.command( @click.command(
...@@ -81,13 +81,7 @@ def send_membership(ctx): ...@@ -81,13 +81,7 @@ def send_membership(ctx):
tui.send_doc_confirmation("membership document for this identity") tui.send_doc_confirmation("membership document for this identity")
# Send the membership signed raw document to the node # Send the membership signed raw document to the node
response = client(bma.blockchain.membership, membership.signed_raw()) send_document(bma.blockchain.membership, membership)
if response.status == 200:
print("Membership successfully sent")
else:
print("Error while publishing membership: {}".format(response.text()))
logging.debug(response.text())
def display_confirmation_table(identity_uid, pubkey, identity_timestamp): def display_confirmation_table(identity_uid, pubkey, identity_timestamp):
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with Silkaj. If not, see <https://www.gnu.org/licenses/>. # along with Silkaj. If not, see <https://www.gnu.org/licenses/>.
import urllib
from duniterpy.api.client import Client from duniterpy.api.client import Client
from silkaj.constants import G1_DEFAULT_ENDPOINT, G1_TEST_DEFAULT_ENDPOINT from silkaj.constants import G1_DEFAULT_ENDPOINT, G1_TEST_DEFAULT_ENDPOINT
...@@ -63,3 +65,13 @@ class EndPoint: ...@@ -63,3 +65,13 @@ class EndPoint:
class ClientInstance: class ClientInstance:
def __init__(self): def __init__(self):
self.client = Client(EndPoint().BMA_ENDPOINT) self.client = Client(EndPoint().BMA_ENDPOINT)
def send_document(bma_path, document):
client = ClientInstance().client
doc_name = document.__class__.__name__
try:
client(bma_path, document.signed_raw())
print(f"{doc_name} successfully sent")
except urllib.error.HTTPError as e:
print(f"Error while publishing {doc_name.lower()}: {e}")
  • matograine @matograine ·
    Maintainer

    When Silkaj encounters an error from the Duniter node, send_document will return 0, which is a success. Should we not return an error code, since something went wrong ?

  • Author Owner

    Thanks for that! We could replace this print() with sys.exit(). I am just afraid it could cause issue in the tx command, since the algorithm is stopped, and therefore the other intermediaries tx are not sent. What do you think? Having exit()s everywhere is also something I want to avoid, in case Silkaj turns into a GUI client. But, you are right for a CLI client, this error should be reported as an exit code in the shell it's running in.

  • Author Owner

    In case we are not sure about tx command and having sys.exit() down in the hierarchy in base functions, we could handle it outside, but it's less elegant, so we can decide on each case whether we want to exit or not the program based on the raised exception:

    def send_document(bma_path, document):
        client = ClientInstance().client
        doc_name = document.__class__.__name__
        client(bma_path, document.signed_raw())
        print(f"{doc_name} successfully sent")
    
    
    # send document cmd
    try:
        send_document(bma_path, document)
    except urllib.error.HTTPError as e:
        sys.exit(f"Error while publishing {document.__class__.__name__.lower()}: {e}")

    But, first, let's check for the tricky tx intermediaries transactions x)

  • Author Owner

    I checked. For cert, membership, and revocation commands, send_document() is at the end of execution of the command/main function. So, this is not a problem for them if there is a sys.exit() call.

    For tx command, in case of:

    • single tx: also at the end of hierarchy, same as the other cmds. Not problematic if it fails.
    • intermediaries tx: a list of intermediaries tx are sent then the final tx. What could happen is that one of the intermediary tx fails to be sent to a Duniter node and exits the program. The planned tx after this one are not sent. This is fine if things get stopped/stuck here since this is summing up sources on to the issuer’s pubkey.

    In summary, I think we a safe adding the sys.exit() call for all cases. Otherwise, I was thinking about something as follow:

    -def send_document(bma_path, document):
    +def send_document(bma_path, document, exit=True)":
        client = ClientInstance().client
        doc_name = document.__class__.__name__
        try:
            client(bma_path, document.signed_raw())
            print(f"{doc_name} successfully sent")
        except urllib.error.HTTPError as e:
            print(f"Error while publishing {doc_name.lower()}: {e}")
    +        if exit:
    +            sys.exit()

    and call send_document(bma_path, intermediary_tx, False) for the intermediaries transactions.


    Thanks for noticing this! It solves an issue I encountered I had with membership tests.

    For you to review: !196 (merged).

  • Please register or sign in to reply
...@@ -393,7 +393,6 @@ def generate_and_send_transaction( ...@@ -393,7 +393,6 @@ def generate_and_send_transaction(
display_sent_tx(outputAddress, tx_amount) display_sent_tx(outputAddress, tx_amount)
print(" - Total: " + str(sum(tx_amounts) / 100)) print(" - Total: " + str(sum(tx_amounts) / 100))
client = nt.ClientInstance().client
transaction = generate_transaction_document( transaction = generate_transaction_document(
issuers, issuers,
tx_amounts, tx_amounts,
...@@ -403,14 +402,7 @@ def generate_and_send_transaction( ...@@ -403,14 +402,7 @@ def generate_and_send_transaction(
OutputbackChange, OutputbackChange,
) )
transaction.sign([key]) transaction.sign([key])
nt.send_document(process, transaction)
response = client(process, transaction.signed_raw())
if response.status == 200:
print("Transaction successfully sent.")
else:
tools.message_exit(
"Error while publishing transaction: {}".format(response.text())
)
def display_sent_tx(outputAddress, amount): def display_sent_tx(outputAddress, amount):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment