Show Posts
|
Pages: [1]
|
I don't think that everything needs to be multisig. If you intend to market this to the public, having a multisig system is going to add a lot of technical complexity for both the tenant and the landlord. In a lot of places, real estate rental has long since moved away from the system of cutting your landlord a check each month, and instead has changed to direct deposits and the like. Who wants to have to manually sign their rental transactions every single month and tie up their money?
The only thing that I think multisig could be useful for is holding a deposit.
So you believe that the platform should take custody of funds on behalf of the landlord?
|
|
|
What do you generally think of the idea as a whole?
The limitation of most buy/sell/rent platforms is the ability to search or filter. Your tech lead should develop a plan including information tracked, fields searchable, filters/options etc and then run it by a peer review a few times. It's easier to change things before the databases are designed. The blockchain can be used to verify the reviews were made by people who stayed there. A future API could even take care of payment and escrow automatically. Yes, the discovery part is very important. We are gonna make sure we provide enough filtering and search capabilities to our community members. Is there anything else that might give you second thought using such platform?
|
|
|
I guess there are many design choices that could be made when it comes to holding funds in behalf of the guest and the host.
What do you generally think of the idea as a whole? If you have crypto and you wanna travel would such service be useful to you? Or if you are a host, would you like to earn crypto this way?
|
|
|
There's a couple of these services out there already, but they only work with fiat. Although, I don't see a lot of platforms that are able to fully deal with renting, and most of them are just to connect the tenant to the landlord.
The one platform that is able to manage bookings is only used for short rental periods, like when you are on holiday (for example, Airbnb).
I'm assuming it'll be a platform where the user would deposit funds into a wallet for their booking, and then for the funds to be released 2 people need to sign off? Otherwise, the person who is paying can just say no and you'll be screwed.
Well, yeah. There is everything out there in fiat! My goal is to create an opportunity for people to earn some crypto doing short term rental. As far as the platform goes, yes. There is gonna be multisig wallet and we the platform act as an escrow. I have built the multisig engine (needs more refinement though) and the front end and mobile apps are under development! I need help! Can't do it alone! For the record, this is not a side project! This is not a hack or simply a mean to satisfy ones crypto curiosity! I want to build real business at scale and bring value to people around the world! And until people, at scale, tell me they don' want it, I won't quit!
|
|
|
Hi Everyone, I’m building a peer-to-peer real estate rental platform by leveraging multi-sig in BTC. The first version is gonna be very simple with three keys shared between host, guest and the platform acting as escrow. There are more details that I’m currently working in but I need help! Is anybody interested? Also please give me some negative feedback if you can
|
|
|
Hi everyone! I have an unsigned transaction consuming p2sh inputs, list of redeem scripts, master private key and the corresponding derivation paths and I would like to "half-sign" this multi sig transaction using this SPV library. https://github.com/breadwallet/breadwallet-core/blob/master/BRTransaction.c
I assume I need to parse the unsigned txHex using: // buf must contain a serialized tx // retruns a transaction that must be freed by calling BRTransactionFree() BRTransaction *BRTransactionParse(const uint8_t *buf, size_t bufLen) { assert(buf != NULL || bufLen == 0); if (! buf) return NULL; int isSigned = 1, witnessFlag = 0; uint8_t *sBuf; size_t i, j, off = 0, witnessOff = 0, sLen = 0, len = 0, count; BRTransaction *tx = BRTransactionNew(); BRTxInput *input; BRTxOutput *output; tx->version = (off + sizeof(uint32_t) <= bufLen) ? UInt32GetLE(&buf[off]) : 0; off += sizeof(uint32_t); tx->inCount = (size_t)BRVarInt(&buf[off], (off <= bufLen ? bufLen - off : 0), &len); off += len; if (tx->inCount == 0 && off + 1 <= bufLen) witnessFlag = buf[off++]; if (witnessFlag) { tx->inCount = (size_t)BRVarInt(&buf[off], (off <= bufLen ? bufLen - off : 0), &len); off += len; }
array_set_count(tx->inputs, tx->inCount); for (i = 0; off <= bufLen && i < tx->inCount; i++) { input = &tx->inputs[i]; input->txHash = (off + sizeof(UInt256) <= bufLen) ? UInt256Get(&buf[off]) : UINT256_ZERO; off += sizeof(UInt256); input->index = (off + sizeof(uint32_t) <= bufLen) ? UInt32GetLE(&buf[off]) : 0; off += sizeof(uint32_t); sLen = (size_t)BRVarInt(&buf[off], (off <= bufLen ? bufLen - off : 0), &len); off += len; if (off + sLen <= bufLen && BRAddressFromScriptPubKey(NULL, 0, &buf[off], sLen) > 0) { BRTxInputSetScript(input, &buf[off], sLen); input->amount = (off + sLen + sizeof(uint64_t) <= bufLen) ? UInt64GetLE(&buf[off + sLen]) : 0; off += sizeof(uint64_t); isSigned = 0; } else if (off + sLen <= bufLen) BRTxInputSetSignature(input, &buf[off], sLen); off += sLen; if (! witnessFlag) BRTxInputSetWitness(input, &buf[off], 0); // set witness to empty byte array input->sequence = (off + sizeof(uint32_t) <= bufLen) ? UInt32GetLE(&buf[off]) : 0; off += sizeof(uint32_t); } tx->outCount = (size_t)BRVarInt(&buf[off], (off <= bufLen ? bufLen - off : 0), &len); off += len; array_set_count(tx->outputs, tx->outCount); for (i = 0; off <= bufLen && i < tx->outCount; i++) { output = &tx->outputs[i]; output->amount = (off + sizeof(uint64_t) <= bufLen) ? UInt64GetLE(&buf[off]) : 0; off += sizeof(uint64_t); sLen = (size_t)BRVarInt(&buf[off], (off <= bufLen ? bufLen - off : 0), &len); off += len; if (off + sLen <= bufLen) BRTxOutputSetScript(output, &buf[off], sLen); off += sLen; } for (i = 0, witnessOff = off; witnessFlag && off <= bufLen && i < tx->inCount; i++) { input = &tx->inputs[i]; count = (size_t)BRVarInt(&buf[off], (off <= bufLen ? bufLen - off : 0), &len); off += len; for (j = 0, sLen = 0; j < count; j++) { sLen += (size_t)BRVarInt(&buf[off + sLen], (off + sLen <= bufLen ? bufLen - (off + sLen) : 0), &len); sLen += len; } if (off + sLen <= bufLen) BRTxInputSetWitness(input, &buf[off], sLen); off += sLen; } tx->lockTime = (off + sizeof(uint32_t) <= bufLen) ? UInt32GetLE(&buf[off]) : 0; off += sizeof(uint32_t); if (tx->inCount == 0 || off > bufLen) { BRTransactionFree(tx); tx = NULL; } else if (isSigned && witnessFlag) { BRSHA256_2(&tx->wtxHash, buf, off); sBuf = malloc((witnessOff - 2) + sizeof(uint32_t)); UInt32SetLE(sBuf, tx->version); memcpy(&sBuf[sizeof(uint32_t)], &buf[sizeof(uint32_t) + 2], witnessOff - (sizeof(uint32_t) + 2)); UInt32SetLE(&sBuf[witnessOff - 2], tx->lockTime); BRSHA256_2(&tx->txHash, sBuf, (witnessOff - 2) + sizeof(uint32_t)); free(sBuf); } else if (isSigned) { BRSHA256_2(&tx->txHash, buf, off); tx->wtxHash = tx->txHash; } return tx; }
and then sign it using: // adds signatures to any inputs with NULL signatures that can be signed with any keys // forkId is 0 for bitcoin, 0x40 for b-cash, 0x4f for b-gold // returns true if tx is signed int BRTransactionSign(BRTransaction *tx, int forkId, BRKey keys[], size_t keysCount) { UInt160 pkh[keysCount]; size_t i, j; assert(tx != NULL); assert(keys != NULL || keysCount == 0); for (i = 0; tx && i < keysCount; i++) { pkh[i] = BRKeyHash160(&keys[i]); } for (i = 0; tx && i < tx->inCount; i++) { BRTxInput *input = &tx->inputs[i]; const uint8_t *hash = BRScriptPKH(input->script, input->scriptLen); j = 0; while (j < keysCount && (! hash || ! UInt160Eq(pkh[j], UInt160Get(hash)))) j++; if (j >= keysCount) continue; const uint8_t *elems[BRScriptElements(NULL, 0, input->script, input->scriptLen)]; size_t elemsCount = BRScriptElements(elems, sizeof(elems)/sizeof(*elems), input->script, input->scriptLen); uint8_t pubKey[BRKeyPubKey(&keys[j], NULL, 0)]; size_t pkLen = BRKeyPubKey(&keys[j], pubKey, sizeof(pubKey)); uint8_t sig[73], script[1 + sizeof(sig) + 1 + sizeof(pubKey)]; size_t sigLen, scriptLen; UInt256 md = UINT256_ZERO; if (elemsCount == 2 && *elems[0] == OP_0 && *elems[1] == 20) { // pay-to-witness-pubkey-hash uint8_t data[_BRTransactionWitnessData(tx, NULL, 0, i, forkId | SIGHASH_ALL)]; size_t dataLen = _BRTransactionWitnessData(tx, data, sizeof(data), i, forkId | SIGHASH_ALL); BRSHA256_2(&md, data, dataLen); sigLen = BRKeySign(&keys[j], sig, sizeof(sig) - 1, md); sig[sigLen++] = forkId | SIGHASH_ALL; scriptLen = BRScriptPushData(script, sizeof(script), sig, sigLen); scriptLen += BRScriptPushData(&script[scriptLen], sizeof(script) - scriptLen, pubKey, pkLen); BRTxInputSetSignature(input, script, 0); BRTxInputSetWitness(input, script, scriptLen); } else if (elemsCount >= 2 && *elems[elemsCount - 2] == OP_EQUALVERIFY) { // pay-to-pubkey-hash uint8_t data[_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)]; size_t dataLen = _BRTransactionData(tx, data, sizeof(data), i, forkId | SIGHASH_ALL); BRSHA256_2(&md, data, dataLen); sigLen = BRKeySign(&keys[j], sig, sizeof(sig) - 1, md); sig[sigLen++] = forkId | SIGHASH_ALL; scriptLen = BRScriptPushData(script, sizeof(script), sig, sigLen); scriptLen += BRScriptPushData(&script[scriptLen], sizeof(script) - scriptLen, pubKey, pkLen); BRTxInputSetSignature(input, script, scriptLen); BRTxInputSetWitness(input, script, 0); } else { // pay-to-pubkey uint8_t data[_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)]; size_t dataLen = _BRTransactionData(tx, data, sizeof(data), i, forkId | SIGHASH_ALL);
BRSHA256_2(&md, data, dataLen); sigLen = BRKeySign(&keys[j], sig, sizeof(sig) - 1, md); sig[sigLen++] = forkId | SIGHASH_ALL; scriptLen = BRScriptPushData(script, sizeof(script), sig, sigLen); BRTxInputSetSignature(input, script, scriptLen); BRTxInputSetWitness(input, script, 0); } } if (tx && BRTransactionIsSigned(tx)) { uint8_t data[BRTransactionSerialize(tx, NULL, 0)]; size_t len = BRTransactionSerialize(tx, data, sizeof(data)); BRTransaction *t = BRTransactionParse(data, len); if (t) tx->txHash = t->txHash, tx->wtxHash = t->wtxHash; if (t) BRTransactionFree(t); return 1; } else return 0; }
Can anyone explain to me what's the purpose of BRScriptPushData in the signing step? Thanks a lot!
|
|
|
|