Ethereum signatures must conform to the secp256k1 curve R, S and V values, requiring the V value must be either 27 or 28.
I was wondering what the legacy reason for two valid V values is?
Was this caused by the Ethereum classic hardfork? Do current wallet implementations only use one of them and the other is the legacy value that carried over?
See: https://github.com/ethereum/go-ethereum/blob/55599ee95d4151a2502465e0afc7c47bd1acba77/internal/ethapi/api.go#L452-L459
// EcRecover returns the address for the account that was used to create the signature.
// Note, this function is compatible with eth_sign and personal_sign. As such it recovers
// the address of:
// hash = keccak256("\x19Ethereum Signed Message:\n"${message length}${message})
// addr = ecrecover(hash, signature)
//
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
// the V value must be be 27 or 28 for legacy reasons.
//
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
if len(sig) != 65 {
return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
}
if sig[64] != 27 && sig[64] != 28 {
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
}
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
rpk, err := crypto.Ecrecover(signHash(data), sig)
if err != nil {
return common.Address{}, err
}
pubKey := crypto.ToECDSAPub(rpk)
recoveredAddr := crypto.PubkeyToAddress(*pubKey)
return recoveredAddr, nil
}
R and S aren't sufficient to recover the public key of the signer. V provides the extra bit of information required to disambiguate. See https://ethereum.stackexchange.com/questions/15766/what-does-v-r-s-in-eth-gettransactionbyhash-mean.
Related
Context: I'm developing a TF Provider.
I'm adding the CustomizeDiff function instead however there's a gotcha: if a resource attribute references another attribute (foo = bar.resourcefoo.xyz), it seems to return "" as value on an initial terraform plan run.
Its signature is
// See Resource documentation.
type CustomizeDiffFunc func(context.Context, *ResourceDiff, interface{}) error
and ResourceDiff doesn't have IsNewResource() that ResourceData has. Are there any workarounds to have something similar to IsNewResource()?
In other words, I want something similar to
func SetDiff(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error {
if diff.IsNewResource() { return nil }
// Otherwise run the check
...
// If we are increasing "size" then the new value must be
// a multiple of the old value.
if new.(int) <= old.(int) {
return nil
}
Some hacks I discovered:
#1:
if diff.Id() == "" { return nil }
#2:
if diff.HasChange()
I'm trying to use go on a raspberry pi to query bluetooth low energy devices. It's functional, I can connect to the device I want and iterate through the services and characteristics of the connected device. Now I'm just trying to streamline things and just read/write the values I'm interested in. It isn't working.
Code:
func onPeriphConnected(p gatt.Peripheral, err error) {
fmt.Println("Connected")
defer p.Device().CancelConnection(p)
if err := p.SetMTU(500); err != nil {
fmt.Printf("Failed to set MTU, err: %s\n", err)
}
batteryServiceId := gatt.MustParseUUID("180f")
// Direct read attempt (not working)
batterySerivce := gatt.NewService(batteryServiceId)
batteryLevelUUID := gatt.MustParseUUID("2a19")
batteryChar := gatt.NewCharacteristic(batteryLevelUUID,batterySerivce,gatt.Property(0x12),0,0)
e, err := p.ReadCharacteristic(batteryChar)
if err != nil {
fmt.Printf("Failed to read battery level, err: %s\n", err)
} else {
fmt.Println(e)
}
// iterate services read (working)
ss, err := p.DiscoverServices(nil)
if err != nil {
fmt.Printf("Failed to discover services, err: %s\n", err)
return
}
for _, s := range ss {
if(s.UUID().Equal(batteryServiceId)) {
fmt.Println("Found the battery service")
// Discovery characteristics
cs, err := p.DiscoverCharacteristics(nil, s)
if err != nil {
fmt.Printf("Failed to discover characteristics, err: %s\n", err)
continue
}
for _, c := range cs {
msg := " Characteristic " + c.UUID().String()
if len(c.Name()) > 0 {
msg += " (" + c.Name() + ")"
}
msg += "\n properties " + c.Properties().String()
fmt.Println(msg)
if (c.Properties() & gatt.CharRead) != 0 {
b, err := p.ReadCharacteristic(c)
if err != nil {
fmt.Printf("Failed to read characteristic, err: %s\n", err)
continue
}
fmt.Printf(" value %x\n", b)
}
}
}
}
}
Results:
Connected
[10 0 0 1]
Found the battery service
Characteristic 2a19 (Battery Level)
properties read notify
value 53
You can see where I expect to get a hex value of 53 I'm instead getting an array of [10 0 0 1]. I'm pretty new to go so I'm probably missing something here or just assembling my read incorrectly. Any pointers are much appreciated. Thanks!
A link to the appropriate documentation would be advisable. I don't know if this link is correct as there seem to be multiple different versions of package gatt.
Edit: see also https://godoc.org/github.com/paypal/gatt/examples/service#NewBatteryService at https://github.com/paypal/gatt/blob/master/examples/service/battery.go, which appears to show the right way of creating a battery service directly. Original answer below.
Having had a quick scan through said documentation, two things leap out at me:
The battery level ID is 2a19. The battery service ID is 180f. You use:
batteryServiceId := gatt.MustParseUUID("180f")
batterySerivce := gatt.NewService(batteryServiceId)
batteryChar := gatt.NewCharacteristic(batteryLevelUUID, batterySerivce,
gatt.Property(0x12), 0, 0)
e, err := p.ReadCharacteristic(batteryChar)
(I kept variable name spellings, but added a bit of white space to fit better on the StackOverflow display.) You never call NewDescriptor nor either of AddDescriptor or SetDescriptors on batteryChar. Are such calls required? I don't know; the documentation doesn't say. But the call that works uses DiscoverServices followed by DiscoverCharacteristics, which perhaps does create these (documented but undescribed) Descriptors. They look like they interpose themselves in value-oriented operations, so they might be critical.
Looking further at the code, after or instead of creating a characteristic directly, I think you do have to at least link the characteristic back into the service. The right call might be AddCharacteristic or SetCharacteristics. See this chunk of code in DiscoverCharacteristics.
(Minor.) gatt.Property(0x12) is definitely the wrong way to construct the constant. You probably should use:
gatt.Property.CharRead | gatt.Property.CharNotify
i am trying to store fund transfer record on hyperledger fabric. i have written chain code in go lang. it work fine when i add data in initLedger function. but when i call it from other function like createTransfer(i will provide both codes) it show successful transaction but when i retrieve chain data .it does not appear in it.
transfer struct
type Transfer struct {
TransferID string `json:"transferID"`
FromAccount string `json:"fromAccount"`
ToAccount string `json:"toAcount"`
Amount string `json:"amount"`
}
this function write data to ledger: it workis fine when i directly call it in initLedger method
func writeTransferToLedger(APIStub shim.ChaincodeStubInterface, transfers []Transfer) sc.Response {
for i := 0; i < len(transfers); i++ {
key := transfers[i].TransferID
chkBytes, _ := APIStub.GetState(key)
if chkBytes == nil {
asBytes, _ := json.Marshal(transfers[i])
err := APIStub.PutState(transfers[i].TransferID, asBytes)
if err != nil {
return shim.Error(err.Error())
}
} else {
msg := "Transfer already exist" + key + " Failure---------------"
return shim.Error(msg)
}
}
return shim.Success([]byte("Write to Ledger"))
}
Call writeToTransferLedger method with in createTransfer function:
func (s *SmartContract) createTransfer(APIStub shim.ChaincodeStubInterface, args []string) sc.Response {
if len(args) != 4 {
return shim.Error("Incorrect Number of arguments for transfer func, Expecting 4")
}
transfers := []Transfer{Transfer{TransferID: args[0], FromAccount: args[1], ToAccount: args[2], Amount: args[3]}}
writeTransferToLedger(APIStub, transfers)
return shim.Success([]byte("stored:" + args[0] + args[1] + args[2] + args[3]))
}
when i call createTransfer from nodesdk code it execute succefully but when i retrive data from chain code not thing return.
i Expect it to work with createTransfer function as it is working with writeTransferToLedger.
inside initLedger method i have created transfer struct with given data and called writeTransferToLedger function code is given below:
transfer := []Transfer{
{TransferID: "1233", FromAccount: "US_John_Doe_123", ToAccount: "UK_Alice_456", Amount: "200"},
{TransferID: "231", FromAccount: "JPY_Alice_456", ToAccount: "UK_John_Doe", Amount: "3000"},
}
writeTransferToLedger(APIstub, transfer)
thanks for your help . i have resolved the issue.
i was calling invoke function when trying to retrieve data from customer ledger.
i have to query the ledger and get transfer data from ledger.
I forked this project, so I am not as familiar with all of the details: https://github.com/nebs/hello-bluetooth/blob/master/HelloBluetooth/NSData%2BInt8.swift.
This is all part of an extension of NSData that the I am using to send 8-bit values to an Arduino.
func int8Value() -> Int8 {
var value: Int8 = 0
copyBytes(to: &UInt8(value), count: MemoryLayout<Int8>.size) //BUG
return value
}
However, it appears in Swift 3 that this now throws an error in the copyBytes section. Although I have seen some solutions such as passing an address in the parameter, I did not want to risk breaking the remaining parts of the code. Any suggestions on what to do for this?
The original code was incorrect. UInt8(value) generates a new, immutable value which you cannot write to. I assume the old compiler just let you get away with it, but it was never correct.
What they meant to do was to write to the expected type, and then convert the type at the end.
extension Data {
func int8Value() -> Int8 {
var value: UInt8 = 0
copyBytes(to: &value, count: MemoryLayout<UInt8>.size)
return Int8(value)
}
}
That said, I wouldn't do it that way today. Data will coerce its values to whatever type you want automatically, so this way is safer and simpler and very general:
extension Data {
func int8ValueOfFirstByte() -> Int8 {
return withUnsafeBytes{ return $0.pointee }
}
}
Or this way, which is specific to ints (and even simpler):
extension Data {
func int8Value() -> Int8 {
return Int8(bitPattern: self[0])
}
}
I am trying to get the unique message ID through JavaMail, so that I can identify mail without the context of a particular IMAP-folder later. The code I've written so far is as follows:
def fp = new FetchProfile()
fp.add(FetchProfile.Item.ENVELOPE)
fp.add(FetchProfile.Item.FLAGS)
fp.add(FetchProfile.Item.CONTENT_INFO)
fp.add(javax.mail.UIDFolder.FetchProfileItem.UID)
fp.add("X-mailer")
fp.add("X-GM-MSGID") // Attribute for retrieving the ID in the fetch (?)
uIDFolder.fetch(iMAPmessages, fp);
iMAPmessages.each { msg ->
println msg.dump()
}
Which results in the following output (for one message):
<com.sun.mail.imap.IMAPMessage#14c04449
bs=com.sun.mail.imap.protocol.BODYSTRUCTURE#5ac31f43
envelope=com.sun.mail.imap.protocol.ENVELOPE#40399642
items=[:]
receivedDate=Mon Jul 28 12:18:38 MSK 2014
size=3147
peek=false
uid=991
modseq=-1
sectionId=null
type=null
subject=null
description=null
headersLoaded=false
loadedHeaders=[X-GM-MSGID:X-GM-MSGID, X-MAILER:X-mailer]
dh=null
content=null
contentStream=null
headers=javax.mail.internet.InternetHeaders#4b7e7ff
flags=com.sun.mail.imap.protocol.FLAGS#20
modified=false
saved=true
cachedContent=null
strict=true
msgnum=372
expunged=false
folder=INBOX
session=javax.mail.Session#4f0dc86c>
The Envelope:
<com.sun.mail.imap.protocol.ENVELOPE#34ea0af2
msgno=371
date=Sun Jul 27 17:46:08 MSK 2014
subject=Re: Require
from=[From <from#gmail.com>]
sender=[sender <sender#gmail.com>]
replyTo=[From <from#gmail.com>]
to=[receiver <receiver#gmail.com>, =?ISO-8859-1?Q?Johan_W=E4ngl=F6f?= <example#gmail.com>]
cc=null
bcc=null
inReplyTo=<CAHr+Gay-ZX0U-pFuwQUMziyECTOVrLNn-XLtc643DYXwgtdDFQ#mail.gmail.com>
messageId=<CAHr+GawnCxaT476K8Rm1MeQNPx8HOfL+VqM0ThMydfTNR12rBg#mail.gmail.com>>
The last attribute added to the fetch profile is the special attribute to fetch the unique ID (https://developers.google.com/gmail/imap_extensions#access_to_the_gmail_unique_message_id_x-gm-msgid).
The messages contains no unique message ID, as far as I can tell. Am I doing something completely wrong?
Trace of the IMAP Session
* 372 FETCH (UID 991 RFC822.SIZE 3147 INTERNALDATE "28-Jul-2014 08:18:38 +0000" FLAGS (\Seen) ENVELOPE ("Mon, 28 Jul 2014 10:18:38 +0200" "Hej du" (("Emil Tholin" NIL "emtholin" "gmail.com")) (("Emil Tholin" NIL "emtholin" "gmail.com")) (("Emil Tholin" NIL "emtholin" "gmail.com")) (("Emil Tholin" NIL "emtholin" "gmail.com")) NIL NIL NIL "<CADsZLRxveuyQX5gXVHvr8ca57yCLopJEc+TpuL2GS-57Kq+yqg#mail.gmail.com>") BODYSTRUCTURE ((("TEXT" "PLAIN" ("CHARSET" "UTF-8") NIL NIL "7BIT" 13 1 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "UTF-8") NIL NIL "7BIT" 34 1 NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "001a11c1250ef810aa04ff3c91b5") NIL NIL)("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "rygg.txt") NIL NIL "BASE64" 2138 0 NIL ("ATTACHMENT" ("FILENAME" "rygg.txt")) NIL) "MIXED" ("BOUNDARY" "001a11c1250ef810af04ff3c91b7") NIL NIL) BODY[HEADER.FIELDS (X-mailer X-GM-MSGID)] {4}
)
A4 OK Success
A5 CLOSE
A5 OK Returned to authenticated state. (Success)
DEBUG IMAPS: added an Authenticated connection -- size: 1
specificFolderHeaders() - Closing the mail connection
A6 LOGOUT
* BYE LOGOUT Requested
A6 OK 73 good day (Success)
DEBUG IMAPS: IMAPStore connection dead
DEBUG IMAPS: IMAPStore cleanup, force false
DEBUG IMAPS: IMAPStore cleanup done
Use the Gmail-specific APIs in the latest release of JavaMail.
Bill hit the nail on the head, but I just thought I'd share the minor issues I faced.
The code I posted in my question didn't change much:
def messages = []
def fp = new FetchProfile()
fp.add(FetchProfile.Item.ENVELOPE)
fp.add(FetchProfile.Item.FLAGS)
fp.add(javax.mail.UIDFolder.FetchProfileItem.UID)
fp.add("X-mailer")
//Google specific attributes
fp.add(GmailFolder.FetchProfileItem.MSGID)
fp.add(GmailFolder.FetchProfileItem.THRID)
uIDFolder.fetch(iMAPmessages, fp);
iMAPmessages.each { msg ->
GmailMessage gmsg = (GmailMessage) msg
println Long.toHexString(gmsg.getMsgId().toLong()) //Eureka!
}
The part that took some time to get right was to connect to gimap with an authorization token properly:
def connect(mailAccount) {
if (mailAccount.provider == "Gmail") {
Properties props = new Properties();
props.put("mail.store.protocol", "gimaps");
props.put("mail.gimaps.sasl.enable", "true"); // Note the "gimaps"
props.put("mail.gimaps.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, mailAccount.token);
Session session = Session.getDefaultInstance(props, null);
final String emptyPassword = ""; // Since we authorize with token
GmailStore store = (GmailStore) session.getStore("gimaps");
store.connect(
"imap.gmail.com",
993,
mailAccount.emailAddress,
emptyPassword);
return store;
}
else {
OAuth2Authenticator.initialize();
def store = OAuth2Authenticator.connectToImap(
"imap.gmail.com",
993,
mailAccount.emailAddress,
mailAccount.token,
false); // Debug flag
return store;
}
}
Using a separate store for the Gmail-addresses and the neat OAuth2Authenticator (https://code.google.com/p/google-mail-oauth2-tools/source/browse/trunk/java/com/google/code/samples/oauth2/OAuth2Authenticator.java?r=3) for other providers worked great.